Ruby 1.8.7中的幂运算返回错误答案 [英] Exponentiation in Ruby 1.8.7 Returns Wrong Answers

查看:83
本文介绍了Ruby 1.8.7中的幂运算返回错误答案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试在irb中计算3 ** 557时遇到了这个问题。
Ruby和MacRuby都安装在我的Mac(OS X 10.8)中。红宝石的版本是1.8.7,MacRuby 0.12(红宝石1.9.2)。
rib和macirb在3 ** 557的计算上给了我两个不同的答案。 (macirb是对的。)

  $ irb 
>> 3 ** 557
=> 54755702179342762063551440788945541007926808765326951193810107165429610423703291760740244724326026031331319131042725875729185204428725368897246765869312009656158752422433804081509847538725260067441221876380409625089341099341098377554287644471346832109666971979603603


3 ** 557
=> 57087217942658063217290581978966727348872586279944803346410228520919738045995056049600505293676159316424182057188​​73024870792298574146706706801801530124457053654660748791998102687725094941415661385633634192239538546546139 $ 546 $ 1
。 3 ** 5337,这次我得到的答案是相同的。



所以,这是Ruby 1.8.7中的bug,还是我应该使用另一种方式来计算幂?

解决方案

计算时,当数字超出Fixnum的范围时,Ruby应该从Fixnum转换为Bignum。对于旧版本的Ruby,使用**运算符将失败:

  $ ruby​​ --version 
ruby​​ 1.8。 7(2012-02-08 patchlevel 358)[universal-darwin12.0]
$ irb
> 2 ** 62
=> 4611686018427387904
> 2 ** 63
=> -9223372036854775808
> 2 ** 64
=> 0

失败的地方取决于体系结构的字长。在此示例中,iMac上的64位字。在内部,Fixnum强制转换为长整数,并且运算符使用long进行处理。 long溢出时出现字长,而Ruby不满意地返回0。



请注意,*运算符正常工作(转换为Bignum),而**失败:

 >>: a = 2 ** 62 
=> 4611686018427387904
> 2 ** 63
=> -9223372036854775808
> a * 2
=> 9223372036854775808
> 2 ** 64
=> 0
>> a * 4
=> 18446744073709551616

移动到较新版本的Ruby即可解决此问题。如果您无法升级到新版本,请避免大功率使用Fixnum和**。


I met this problem when I tried to compute 3**557 in irb. Ruby and MacRuby both are installed in my Mac (OS X 10.8). And the version of ruby is 1.8.7, of MacRuby 0.12 (ruby 1.9.2). rib and macirb gave me two different answers on computation of 3**557. (macirb's is right.)

$ irb
>> 3**557
=> 54755702179342762063551440788945541007926808765326951193810107165429610423703291760740244724326099993131913104272587572918520442872536889724676586931200965615875242243330408150984753872526006744122187638040962508934109837755428764447134683114539218909666971979603

$ macirb
irb(main):001:0> 3**557
=> 57087217942658063217290581978966727348872586279944803346410228520919738045995056049600505293676159316424182057188730248707922985741467061108015301244570536546607487919981026877250949414156613856336341922395385463291076789878575326012378057561766997352898452974964563

And then I tried something bigger, e.g. 3**5337, and I got the same answer this time.

So, is this a bug in Ruby 1.8.7, or I should use another way to compute exponentiation?

解决方案

When calculating, Ruby is supposed to convert from Fixnum to Bignum when the numbers go beyond the bounds of Fixnum. For older versions of Ruby, this fails with the ** operator:

$ ruby --version
ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]
$ irb
>> 2 ** 62
=> 4611686018427387904
>> 2 ** 63
=> -9223372036854775808
>> 2 ** 64
=> 0

Where it fails depends on the word size of the architecture. 64-bit words on the iMac in this example. Internally, the Fixnum is cast to a long integer, and the operator is handled with longs. The longs overflow at word size, and Ruby is ungracefully handling this by returning 0.

Note that the * operator works correctly (converting to Bignum), where the ** fails:

>> a = 2 ** 62
=> 4611686018427387904
>> 2 ** 63
=> -9223372036854775808
>> a * 2
=> 9223372036854775808
>> 2 ** 64
=> 0
>> a * 4
=> 18446744073709551616

Moving to a newer version of Ruby will fix this. If you can't move to a newer version, then avoid using Fixnum and ** with large powers.

这篇关于Ruby 1.8.7中的幂运算返回错误答案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆