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?
Using 1.9.3 produces the correct result. Unless you have a really good reason, try to use 1.9.3 or better since 1.8.7 is being phased out.
It's also worth noting that after testing with 1.8.7-p358 on Linux I get the correct answer as well. it could be a bug in the particular version of 1.8.7 you're using.
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:
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:
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.
It's not related to exponentiation explicitly. I think it's in some way related to the transition from 63 to 64 bits required for representation, though this doesn't seem 100% consistent.
and
yet
Also: running irb in 32-bit mode (
arch -i386 irb
), I don't see this at this point, but earlier:Writing your own exponentiation method seems to be another way to do it that doesn't produce errors:
'10' to any power should begin with a single '1' and be followed by nothing but zeros. Ruby's
**
function:Custom
xpnt
method:This is definitely a bug. It is probably dependent on the processor and/or compilation options.
I wouldn't be surprised if it was fixed by this commit.
As others have stated, only security fixes make it to 1.8.7 nowadays, so upgrade to 1.9.3.