一尘不染

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

c#

请考虑以下代码和注释:

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的情况,但是:

为什么要在被零除的整数中使用double返回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实际上是非常非常小的分数,这将导致Infinity …


阅读 428

收藏
2020-05-19

共1个答案

一尘不染

简而言之: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 / x随着x接近零,接近无穷大。因此,从这个角度来看,如果我们仍然无法n / m 精确地 表示大部分分数,则将x / 0案例视为近似值并给出其 接近 的值 __-再次,至少定义了无限。

2020-05-19