44

请考虑以下代码和注释:

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   

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

为什么在被零除中使用双精度返回 Infinity 而不是抛出异常?这是设计使然还是错误?

只是为了好玩,我也在 VB.NET 中做了这个,结果“更一致”:

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

编辑:

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

Console.WriteLine(1 / .0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);

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

4

5 回答 5

37

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

VB.NET 做的事情有点不同。整数除法使用运算符自动生成浮点值/。这是为了允许开发人员编写,例如,表达式1 / 2,并让它评估为0.5,有些人会认为这是直观的。如果您想查看与 C# 一致的行为,请尝试以下操作:

Console.WriteLine(1 \ 0)

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

同样,试试这个:

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

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

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

于 2011-01-05T22:34:55.040 回答
8

double 是一个浮点数,而不是一个精确的值,所以从编译器的角度来看,你真正除以的是接近零的东西,但不完全是零。

于 2011-01-05T22:11:04.400 回答
2

这是设计使然,因为该double类型符合IEEE 754浮点运算标准。查看Double.NegativeInfinityDouble.PositiveInfinity的文档。

这个常数的值是一个正{或负}数除以零的结果。

于 2011-01-05T22:28:04.533 回答
2

因为“数字”浮点不是那种类型的。浮点运算:

  • 不具有关联性
  • 不是分布式的
  • 可能没有乘法逆元

(有关一些示例,请参见http://www.cs.uiuc.edu/class/fa07/cs498mjg/notes/floating-point.pdf )

浮点是一种解决特定问题的结构,并且在不应该使用的时候被全部使用。我认为它们非常糟糕,但这是主观的。

于 2013-03-18T21:59:28.190 回答
1

这可能与 IEEE 标准浮点数和双精度浮点数具有指定的“无穷大”值这一事实有关。.NET 只是在硬件级别公开了一些已经存在的东西。

从逻辑上看,为什么这是有道理的,请参见 kekekela 的回答。

于 2011-01-05T22:27:30.540 回答