Ruby中的乘法导致溢出?

时间:2012-11-06 20:14:17

标签: ruby math multiplication

所以,我从理论上读到,Ruby中的整数没有最大值,并且它们可以根据需要大小。但是,当我乘以以下是导致负值(我认为这是溢出的迹象?):

  
    

44404051714 * 44404051714     => -2081807267335685116

  

有人可以向我解释一下吗?

1 个答案:

答案 0 :(得分:3)

这看起来像Ruby的Fixnum类乘法实现中的一个错误。查看来源,numeric.cfixmul函数中的以下行(严重剪切)突然出现:

...
2645:   long a, b;
...
2663:   c = a * b;
2664:   r = LONG2FIX(c);
...
2667:   if (FIX2LONG(r) != c || c/a != b) {
2668:       r = rb_big_mul(rb_int2big(a), rb_int2big(b));
...

如果我正确读取它,那是来自正在进行Fixnum乘法的代码,以及应该进行溢出检测的代码位,以确定结果是否应该实际重新计算为{ {1}}。麻烦的是它是错误的C代码:Bignuma类型为long,如果b溢出则根据C标准产生未定义的行为。一个好的编译器可以通过假设溢出永远不会发生在正确的C程序中来利用这一点,并且基于该逻辑可以优化掉溢出检查a * b

因此,如果您的Ruby版本是使用合理的最新编译器编译的(最近版本的Clang将是一个很好的例子),那可能是导致这种情况的原因。

无论如何,我认为值得一个错误报告:即使这不是你所看到的原因,上面的C代码也是可疑的。


编辑:Daniel Fischer在评论中指出有c / a != b声明。理论上,这应该可以防止溢出检查被优化掉。因此,如果 是问题的原因,那么这将使它成为编译器错误,而不是Ruby代码中的错误。