不同值类型之间的除零行为不一致

Pau*_*sik 41 .net c# vb.net divide-by-zero .net-3.5

请考虑以下代码和评论:

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   
Run Code Online (Sandbox Code Playgroud)

我可以理解编译器在运行时主动检查除零常量和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
Run Code Online (Sandbox Code Playgroud)

编辑:

基于kekekela的反馈,我运行了以下导致无穷大:

Console.WriteLine(1 / .0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);
Run Code Online (Sandbox Code Playgroud)

这个测试似乎证实了这个想法,文字的双重0.0实际上是一个非常非常微小的部分,它将导致无限......

Dan*_*Tao 35

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

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

Console.WriteLine(1 \ 0)
Run Code Online (Sandbox Code Playgroud)

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

同样,试试这个:

Dim x As Object = 1 / 0
Console.WriteLine(x.GetType())
Run Code Online (Sandbox Code Playgroud)

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

至于关于不精确的观点,这是另一种看待它的方式.并不是该double类型没有正好为零的值(它确实如此); 相反,该double类型并不意味着首先在数学上提供精确的结果.(某些值可以准确表示,是的.但是计算没有给出准确性的承诺.)毕竟,数学表达式的1 / 0值没有定义(最后我检查过).但1 / x随着x逼近零,接近无穷大.因此,从这个角度来看,如果我们无法n / m 准确地表示大多数分数,那么将该x / 0案例视为近似并给出它所接近的值 - 至少定义无穷大是有意义的.

  • 虽然非常有用,但这个答案也略有错误。答案是错误的,因为除以零不是无穷大——它在数学上是未定义的。真正的答案是双打不是实数(R),正如本答案后半部分所指出的那样。它们是浮点数,而 OP 正试图将实数推理应用于不是实数的东西。它们在很多时候看起来很相似,因为它们被设计为相似,但它们根本不同。双打定义了一个叫做“NaN”的东西,“不是一个数字”,(继续......) (2认同)
  • (cont...) 如果这实际上是实数,这将是一个在数学上更正确的“结果”。然而它没有返回 NaN。原因大致如答案中所述:因为在浮点逻辑中,您通常假设“0.0”是一个非常小的数字。然而,你不能说它_is_一个小数字,说明_is_和零的精确表示是误导性的,因为没有从浮点数到 R 的 1 对 1 映射。而是每个浮点值映射到实数的范围-values,浮点数“0.0”包括_实际_零_和_一系列其他小值。 (2认同)

hei*_*erg 7

double是一个浮点数而不是一个精确的值,所以你真正从编译器的角度划分的是接近于零但不完全为零的东西.

  • @slebetman - 如果双打有"一个正好为零的值的表示",那么为什么双精度区分"+0"和"-0"以及为什么1/+ 0和1/-0给出不同的结果?如果将这些值视为正值或负值太小而无法正常表示,则"有符号零"的概念才有意义.请注意,IEEE 754浮点类型中没有无符号零. (2认同)