不同值类型之间的除以零行为不一致 [英] Inconsistency in divide-by-zero behavior between different value types

查看:32
本文介绍了不同值类型之间的除以零行为不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码和注释:

Console.WriteLine(1/0);//不会编译,错误:被常量零除int i = 0;Console.WriteLine(1/i);//编译、运行、抛出:DivideByZeroException双 d = 0;Console.WriteLine(1/d);//编译,运行,结果为:Infinity

我可以理解编译器在运行时主动检查除以零常量和 DivideByZeroException 但是:

为什么在被零除时使用 double 会返回 Infinity 而不是抛出异常?这是设计使然还是错误?

只是为了踢球,我也在 VB.NET 中这样做了,结果更加一致":

dim d as double = 0.0Console.WriteLine(1/d) ' 编译、运行,结果为:Infinity将 i 调暗为整数 = 0Console.WriteLine(1/i) ' 编译、运行,结果为:InfinityConsole.WriteLine(1/0) ' 编译、运行,结果为:Infinity

根据 kekekela 的反馈,我运行以下结果为无穷大:

<预> <代码> Console.WriteLine(1/.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);

这个测试似乎证实了这个想法,0.0 的字面量实际上是一个非常非常小的分数,会导致无穷大......

解决方案

简而言之:double 类型定义了一个无穷大的值,而 int 类型没有.所以在 double 的情况下,计算的结果是一个值,你可以用给定的类型实际表达它,因为它是定义的.在 int 的情况下,无穷大没有值,因此无法返回准确的结果.因此例外.

VB.NET 做的事情有点不同;整数除法使用 / 运算符自动生成浮点值.这是为了允许开发人员编写表达式 1/2,并将其计算为 0.5,有些人认为这很直观.如果你想看到与 C# 一致的行为,试试这个:

Console.WriteLine(1  0)

请注意上面整数除法 运算符(,而不是/)的使用.我相信你会得到一个异常(或编译错误——不确定是哪个).

同样,试试这个:

Dim x As Object = 1/0Console.WriteLine(x.GetType())

上面的代码会输出System.Double.

至于不精确的观点,这是另一种看待它的方式.并不是 double 类型没有完全为零的值(确实如此);相反,double 类型并不意味着首先提供数学上精确的结果.(某些值可以精确表示,是的.但是计算不能保证准确性.)毕竟,数学表达式的值1/0 未定义(最后我检查过).但是 1/x 随着 x 接近零而接近无穷大.因此,从这个角度来看,如果我们无论如何都不能表示大多数分数 n/m 完全,那么将 x/0 情况视为近似值和给出它接近的值——同样,至少定义了无穷大.

Please consider the following code and comments:

Console.WriteLine(1 / 0); // will not compile, error: Division by constant zero

int i = 0;
Console.WriteLine(1 / i); // compiles, runs, throws: DivideByZeroException

double d = 0;
Console.WriteLine(1 / d); // compiles, runs, results in: Infinity   

I can understand the compiler actively checking for division by zero constant and the DivideByZeroException at runtime but:

Why would using a double in a divide-by-zero return Infinity rather than throwing an exception? Is this by design or is it a bug?

Just for kicks, I did this in VB.NET as well, with "more consistent" results:

dim d as double = 0.0
Console.WriteLine(1 / d) ' compiles, runs, results in: Infinity

dim i as Integer = 0
Console.WriteLine(1 / i) '  compiles, runs, results in: Infinity

Console.WriteLine(1 / 0) ' compiles, runs, results in: Infinity

EDIT:

Based on kekekela's feedback I ran the following which resulted in infinity:

Console.WriteLine(1 / .0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);

This test seems to corroborate the idea and a literal double of 0.0 is actually a very, very tiny fraction which will result in Infinity...

解决方案

In a nutshell: the double type defines a value for infinity while the int type doesn't. So in the double case, the result of the calculation is a value that you can actually express in the given type since it's defined. In the int case, there is no value for infinity and thus no way to return an accurate result. Hence the exception.

VB.NET does things a little bit differently; integer division automatically results in a floating point value using the / operator. This is to allow developers to write, e.g., the expression 1 / 2, and have it evaluate to 0.5, which some would consider intuitive. If you want to see behavior consistent with C#, try this:

Console.WriteLine(1  0)

Note the use of the integer division operator (, not /) above. I believe you'll get an exception (or a compile error--not sure which).

Similarly, try this:

Dim x As Object = 1 / 0
Console.WriteLine(x.GetType())

The above code will output System.Double.

As for the point about imprecision, here's another way of looking at it. It isn't that the double type has no value for exactly zero (it does); rather, the double type is not meant to provide mathematically exact results in the first place. (Certain values can be represented exactly, yes. But calculations give no promise of accuracy.) After all, the value of the mathematical expression 1 / 0 is not defined (last I checked). But 1 / x approaches infinity as x approaches zero. So from this perspective if we cannot represent most fractions n / m exactly anyway, it makes sense to treat the x / 0 case as approximate and give the value it approaches--again, infinity is defined, at least.

这篇关于不同值类型之间的除以零行为不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆