C# 为什么int和decimal抛出DivideByZeroException,但浮点不';T

C# 为什么int和decimal抛出DivideByZeroException,但浮点不';T,c#,dividebyzeroexception,C#,Dividebyzeroexception,据 当您将Int和Decimal除以0时,只有Int和Decimal会抛出dividebyzero异常,但当您将浮点除以0时,结果是无穷大、负无穷大或NaN。为什么会这样?哪些例子的结果是+ve无穷大、-ve无穷大或NaN?IEEE标准委员会,针对可能遇到浮点数学问题的代码范围: 陷阱可用于停止程序,但无法恢复的情况极为罕见。 […] 标志提供了可预测的控制流和速度。它们的使用要求程序员意识到异常情况,但标记粘性允许程序员在必要时延迟处理异常情况 对于一个习惯了异常处理的语言(如C#)的开发人员


当您将Int和Decimal除以0时,只有Int和Decimal会抛出dividebyzero异常,但当您将浮点除以0时,结果是无穷大、负无穷大或NaN。为什么会这样?哪些例子的结果是+ve无穷大、-ve无穷大或NaN?

IEEE标准委员会,针对可能遇到浮点数学问题的代码范围:

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


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

Michael的答案当然是正确的。这是另一种看待它的方式

整数是精确的。当你用7除以3的整数时,你实际上是在问这样一个问题:“我能用7减去3多少次,然后才能变成负数?”。被零除是未定义的,因为没有多少次你可以从七中减去零得到负数

浮点数本质上是不精确的。它们有一定的精度,你最好假设“真实”量在给定的浮点和它附近的浮点之间。此外,浮点数通常表示物理量,且其测量误差远大于表示误差。我认为浮动是围绕一个点的模糊模糊区域


所以,当你在浮点数中把7除以0时,把它看作是把一个相当接近7的数字除以一个相当接近0的数字。显然,一个合理接近零的数字可以使商任意大!因此,这是通过给予无限作为答案而向你们发出的信号;这意味着答案可以任意大,这取决于真实值实际所在的位置。

内置于处理器中的浮点引擎能够为浮点除零生成异常。Windows有一个专用的异常代码,状态为浮点除以零,异常代码为0xC000008E,“浮点除以零”。以及FPU可以报告的其他灾难,如溢出、下溢和不精确结果(也称为非规范化)

它是否这样做是由控制寄存器决定的,程序可以使用类似的辅助函数更改该寄存器。使用Borland工具创建的库通常会这样做,例如,揭穿这些异常

说得委婉一点,这并没有奏效。这是你能想象到的最糟糕的全局变量。将这样的库与其他期望除以零生成无穷大而不是异常的库混合使用是行不通的,几乎不可能处理

因此,现在语言运行时屏蔽所有浮点异常已成为常态。CLR也坚持这一点


处理一个揭露异常的库很棘手,但有一个愚蠢的解决方法。您可以抛出异常并再次捕获它。CLR内的异常处理代码重置控制寄存器。这方面的一个例子如。

所示,因为这是IEEE提出的标准。其背后的原因是什么?可能是为了破坏最少的现有代码?特别是数字库。密切相关:因此,不存在真正的“零”浮点,也不能被0f除。