4

I wrote some code that is supposed to sum n^n for 1 <= n <= 1000. Here's the code:

sum = 0
(1..1000).each do |n|
  sum += n**n
  puts "n = #{n}, sum = #{sum}"
end

For some reason, the output is coming out negative after number 28:

n = 29, sum = -2015400977700573523892329442490139437391867

Any idea why this is happening?

Zach Langley
  • 6,776
  • 1
  • 26
  • 25
  • 1
    Which version of Ruby is this? It should be switching to bignums to avoid the overflow/wrap-around, at least it does in 1.9.3 and 1.8.7. – mu is too short Oct 29 '12 at 22:33
  • 1
    The code works fine for me with 1.8.7, so the conversion to bignums is working fine there as well. And that happens starting with n=16. – qqx Oct 29 '12 at 22:37
  • 1
    Perhaps you should show the output you get for `arr = 1..28`. – mu is too short Oct 29 '12 at 22:38
  • 1
    You are not squaring it. And there is not squaring it by itself other than for 2. – sawa Oct 29 '12 at 22:41
  • On ruby 1.8.7 I get negative values on iteration 28, but on ruby 1.9.3 I get a result I would expect. I suspect something in this algorithm is tricking ruby into not using a `Bignum` when it should... – Alex Wayne Oct 29 '12 at 22:41
  • @Alex: 1.8.7 handles `arr = 1..1000` just fine for me on OSX. – mu is too short Oct 29 '12 at 22:44
  • This guys isn't making this up, there is something here, and now I am very curious myself. I ran this under 2 versions of ruby on my computer, and once on a ruby production server I have. It's not 1.8.7, it's something else... https://gist.github.com/6ba7bf2a7224119ca619 Weird. – Alex Wayne Oct 29 '12 at 22:50
  • Sounds like a bug in the optimizer on whatever patch level you're running. Try a different patch level. – d11wtq Oct 29 '12 at 22:56
  • BTW, you can write that using inject. `(1..1000).inject(0){|sum, n| sum + n ** n}` – d11wtq Oct 29 '12 at 23:00
  • Is your systems 32 bit, or 64 bit? It shouldn't matter, but I'm trying to figure out the factor at play here. Jump into Alex Wayne's gist and add your output (including ruby -v). – d11wtq Oct 29 '12 at 23:13
  • @AlexWayne look at your values for number 15 and 16, they are _both_ 449317984130199828. This is also the point where Ruby should be switching over to Bignums. – matt Oct 29 '12 at 23:16

1 Answers1

4

Looks like this was a bug in 1.8.7 that was fixed by patch 358: Exponentiation in Ruby 1.8.7 Returns Wrong Answers

(The result of a power computation in numeric.c wasn't declared as volatile before this commit, after which overflow behavior seems to have been fixed.)

Community
  • 1
  • 1
pje
  • 21,801
  • 10
  • 54
  • 70