为什么 int 和 decimal 会抛出 DivideByZeroException,而浮点型不会

本文关键字:浮点型 DivideByZeroException int decimal 为什么 | 更新日期: 2023-09-27 18:31:30

根据 http://msdn.microsoft.com/en-us/library/system.dividebyzeroexception.aspx只有 Int 和 Decimal 会在除以 0 时抛出 DivideByZeroException,但是当您将浮点数除以 0 时,结果是无穷大、负无穷大或 NaN。这是为什么呢?有哪些例子,结果是+ve无穷大,-ve无穷大或NaN?

为什么 int 和 decimal 会抛出 DivideByZeroException,而浮点型不会

IEEE标准委员会认为异常处理比它的价值更麻烦,因为浮点数学可能遇到这些类型的代码范围:

陷阱可用于停止程序,但不可恢复的情况极为罕见。
[...]
标志提供可预测的控制流和速度。它们的使用要求程序员意识到异常条件,但标志粘性允许程序员延迟处理异常条件,直到必要。

对于习惯于深度烘焙异常处理的语言(如 C#)的开发人员来说,这可能看起来很奇怪。IEEE 754标准的开发人员正在考虑更广泛的实现(例如嵌入式系统),在这些实现中,这些设施不可用或不可取。

迈克尔的回答当然是正确的。这是另一种看待它的方式。

整数是精确的。当你用整数将七除以三时,你实际上是在问一个问题:"在我必须变成负数之前,我可以从七中减去三多少次?除以零是不确定的,因为没有次数可以从七中减去零得到负数。

浮子本质上是不精确的。它们具有一定的精度,您最好假设"实际"数量介于给定浮点数和附近的浮点数之间。此外,浮点数通常表示物理量,而这些物理量的测量误差远大于表示误差。我认为浮点数是围绕一个点的模糊模糊的涂抹区域。

因此,当你在浮点数中将 7 除以零时,可以将其视为将某个合理接近 7 的数字除以某个合理接近零的数字。 显然,一个合理接近零的数字可以使商任意大!因此,这是通过给出无穷大作为答案来向你发出的信号;这意味着答案可能是任意大的,具体取决于真实值的实际位置。

处理器内置的浮点引擎非常能够生成浮点除以零的异常。 Windows有一个专用的异常代码,STATUS_FLOAT_DIVIDE_BY_ZERO,异常代码0xC000008E"浮点除以零"。 以及 FPU 可以报告的其他事故,例如溢出、下溢和不准确的结果(也称为非正常)。

是否这样做是由控制寄存器决定的,程序可以使用 _controlfp() 等辅助函数更改此寄存器。 例如,使用 Borland 工具创建的库通常会这样做,从而揭示这些异常。

委婉地说,这效果并不好。 这是你能想象到的最糟糕的全局变量。 将此类库与其他期望除以零以生成无穷大而不是异常的库混合在一起是行不通的,而且几乎不可能处理。

因此,语言运行时现在屏蔽所有浮点异常已成为规范。 中左翼政权也坚持这一点。

处理一个揭示异常的库是很棘手的,但有一个愚蠢的解决方法。 您可以引发异常并再次捕获它。 CLR 中的异常处理代码重置控制寄存器。 本答案中显示了这方面的一个例子。