红宝石如何处理零分割?

时间:2013-08-08 12:02:20

标签: ruby zero

我试图找出ruby如何处理零分裂。 Ruby根据类返回不同的结果。这就是我试过的

0/0     # => ZeroDivisionError: divided by 0    
1/0     # => ZeroDivisionError: divided by 0
1.0/0   # => Infinity
0.0/0.0 # => NaN

这里发生了什么?对于上述所有情况,我不应该得到ZeroDivisionError吗?

更新是" Infinity"那么标准数据类型呢?

(1.0/0).class  # => Float

3 个答案:

答案 0 :(得分:10)

Ruby只跟踪IEEE 754 Floating Point Standard。那个维基百科页面在解释你所看到的内容方面并不错。许多现代语言采用相同的方法。

直观地说,你看到的行为非常有意义。一般来说,

1/<small number> = <big number>

因此在极限中,

1/0 -> Infinity    and similarly    -1/0 -> -Infinity

Infinity是浮点子系统理解的常量。另一方面

0 / <any non-zero> = 0

所以我们在0/0上有冲突。它应该是零还是无穷大? IEEE标准答案是“非数字”,您看到的NaN,另一个浮点常数。

常量NaN和加号或减号Infinity以一种有意义的方式在表达式中传播。例如:

Infinity + <any (necessarly finite) number> = Infinity

<any number> + NaN = NaN

更有趣的是:

1 / Infinity = 0

您可以尝试自己:

irb(main):005:0> 1.0 / (1.0 / 0.0)
=> 0.0

以这种方式浮点计算可以继续进行,即使它已经溢出或除以零并且仍然产生一个合理的信息答案(虽然在你知道标准井之后,你会看到依靠答案通常是坏的主意)。

这远不是标准提供的唯一行为。其他人可以选择。但是Ruby会为你做这件事。源文件numeric.c,函数Init_Numeric,设置主机处理器,以便除以零传播无穷大。其他语言可能会做出其他选择,例如生成异常。

答案 1 :(得分:7)

浮点的行为反映了IEEE 754中的标准:

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

将整数除法的运行时错误实现为零的决定在许多其他语言中也很常见,例如Java,C ++,Python。 Python实际上也调用了错误ZeroDivisionError

请参阅sawa's answer了解这些分类和行为的原因。

答案 2 :(得分:4)

重点是浮点数有舍入误差。浮点0.0不一定表示精确的零,或数学意义上的0.0,但是代表在给定精度的情况下舍入到0.0的所有数字。精确0的除法不是数学定义的,但是如果除数恰好具有小的非零绝对值以舍入到0.0,则禁止除0.0将有返回错误的危险。当除数的绝对值不为零时,您不希望程序突然返回错误。在浮点数的情况下,让系统为0.0分配一定数量而不是禁止它更安全。但是这个数字不能以正常方式表示,因此它被指定为NaN或Infinity。对此有误导的是,无穷大在数学意义上并不是无限的。它只是意味着“比在该系统中可以表达的任何其他数字更大的数字”。这解释了以下情况:

1.0/0.0 # => Infinity
0.0/0.0 # => NaN

/的一个参数是浮点数时,Ruby类型 - 将另一个转换为浮点数,所以

1/0.0
1.0/0

1.0/0.0相同。

另一方面,整数0不包含错误,并且精确为零,因此没有这样的危险。提出零分割误差更有意义。这解释了

1/0 # => Error
0/0 # => Error