Ruby 1.8.7中的幂运算返回错误答案 [英] Exponentiation in Ruby 1.8.7 Returns Wrong Answers
问题描述
当我尝试在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
=> 5708721794265806321729058197896672734887258627994480334641022852091973804599505604960050529367615931642418205718873024870792298574146706706801801530124457053654660748791998102687725094941415661385633634192239538546546139 $ 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屋!