【问题标题】:Why does dividing by zero for Float not raise an exception in Ruby?为什么浮点数除以零不会在 Ruby 中引发异常?
【发布时间】:2020-02-28 08:03:52
【问题描述】:

Integer 除以零会产生ZeroDivisionError

0 / 0 # ZeroDivisionError

但是,Float 除以零:

0.0 / 0   #NaN
0 / 0.0   #NaN
0.0 /0.0  #NaN    
1.0 / 0   #Infinity
1 / 0.0   #Infinity
1.0 /0.0  #Infinity

我想知道为什么 Ruby 中 IntegerFloat 的行为会有这种差异?

【问题讨论】:

标签: ruby floating-point


【解决方案1】:

与几乎所有编程语言一样,Ruby 的浮点运算实现符合IEEE 754 标准。

本规范(上面链接)定义了五个必须(至少默认情况下)以特定方式处理的异常:

  • 无效运算:数学上未定义,例如,负数的平方根。默认情况下,返回 qNaN。

  • 除以零:对有限操作数的运算给出精确的无限结果,例如 1/0 或 log(0)。默认情况下,返回 ±infinity。

  • 溢出:结果太大而无法正确表示(即,其具有无限指数范围的指数将大于 emax)。默认情况下,对于最近舍入模式返回 ±infinity(并遵循有向舍入模式的舍入规则)。

  • 下溢:结果非常小(超出正常范围)且不精确。默认情况下,返回次正规或零(遵循舍入规则)。

  • 不精确:精确(即未舍入)结果无法精确表示。默认情况下,返回正确舍入的结果。

因此1.0/0 必须等于+Infinity,并且0.0/0 必须等于NaN


Integer 对象不符合上述标准。 (没有InfinityNaN,所有操作都是精确的。)因此,针对1/0 等操作引发异常是特定于语言的决定。

【讨论】:

  • 顺便说一句,您可能还会遇到浮点数中的一些其他“奇数”行为,例如Float::NAN == Float::NAN #=> false。这再次符合 IEEE 754 规范。
  • 这些异常“必须”以特定方式处理的声明可能会使读者感到困惑。这些结果是默认异常处理下需要的结果。实现可以提供替代的异常处理,其中可以替代任何用户指定的结果。此外,这个答案掩盖了一些触发异常的细节。
  • 另外,应该注意“浮点异常”是数学结果异常的情况。不是 C++ 或 Ruby 类型的异常会导致程序控制发生变化(尽管控制变化可能会发生在备用异常处理中)。
  • @EricPostpischil 我已将我的答案编辑为 (至少默认情况下) 更准确,谢谢。是的,我确实掩盖了构成“异常”的一些细节——但最初的问题只讨论了1/00/0,这是非常简单的场景。
猜你喜欢
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多