193

I am trying to get the sum of 1 + 2 + ... + 1000000000, but I'm getting funny results in PHP and Node.js.

PHP

$sum = 0;
for($i = 0; $i <= 1000000000 ; $i++) {
    $sum += $i;
}
printf("%s", number_format($sum, 0, "", ""));   // 500000000067108992

Node.js

var sum = 0;
for (i = 0; i <= 1000000000; i++) {
    sum += i ;
}
console.log(sum); // 500000000067109000

The correct answer can be calculated using

1 + 2 + ... + n = n(n+1)/2

Correct answer = 500000000500000000, so I decided to try another language.

GO

var sum , i int64
for i = 0 ; i <= 1000000000; i++ {
    sum += i
}
fmt.Println(sum) // 500000000500000000

But it works fine! So what is wrong with my PHP and Node.js code?

Perhaps this a problem of interpreted languages, and that's why it works in a compiled language like Go? If so, would other interpreted languages such as Python and Perl have the same problem?

ST3
  • 8,826
  • 3
  • 68
  • 92
Baba
  • 94,024
  • 28
  • 166
  • 217
  • 36
    you need this: http://php.net/manual/en/book.bc.php , or else wou will bash your head against IEEE 754 till hell freezes over. – tereško Aug 04 '13 at 18:49
  • `bcadd` almost took forever .. I had to give up – Baba Aug 04 '13 at 18:49
  • 1
    Not only NodeJS, but client-side JavaScript also result the same. `500000000067109000` – Ali Aug 04 '13 at 19:17
  • 5
    For handling large numbers in PHP (i.e. 64-bit), use the GMP functions, in this case gmp_add(). – Jeffrey Aug 04 '13 at 22:11
  • I've been playing with this, and I'm a bit mystified as to what's happening under the hood in those two languages to get 500000000067108992. Curiously, I can get exactly 499999999067108992 in C++ by switching from int to double just prior to overflow when summing the series in a loop, and I'm not clear on why I lose precision in that case either. – AHelps Aug 04 '13 at 22:31
  • 113
    For super efficiency, your loops should really start at 1 instead of 0. :P – Graham Borland Aug 04 '13 at 23:27
  • 55
    sum(1 to N) = (N/2)*(N+1) – Phong Aug 05 '13 at 00:42
  • 1
    hmm... I'm getting 499999999500000000 in java (long). Kinda strange – Droidman Aug 05 '13 at 00:43
  • related: http://stackoverflow.com/q/4427020/684934 –  Aug 05 '13 at 03:38
  • @GrahamBorland how does start with `1` improve efficiency ? – Baba Aug 05 '13 at 11:18
  • 5
    @Baba 0 is superflous for your calculation, so there's no need to have an extra iteration of the loop to add 0 to 0. – Brian Warshaw Aug 05 '13 at 11:29
  • @Baba you'll only run the `for` loop 10^9 times instead of (1 + 10^9) times :-p – Cristian Diaconescu Aug 05 '13 at 11:52
  • You could use int-hinting to use integer ops instead of float ops, unfortunately the result doesn't fit in a 32-bit integer. Still, it's worth sharing: https://gist.github.com/jcdickinson/6155436 – Jonathan Dickinson Aug 05 '13 at 12:06
  • @Maver1ck : in java use big integer(http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigInteger.html) for these sort of calculations :) – Abhinav Aug 05 '13 at 12:45
  • Great question. By the way, you could make your Go code even faster using concurrency! – Matt Aug 05 '13 at 16:35
  • @Maver1ck You probably just didn't do an inclusive loop. – Gustav Larsson Aug 05 '13 at 17:25
  • 1
    Hmm... I'm getting -5340232216128654848 from the Go code (go1.1.1) – voidraen Aug 05 '13 at 18:45
  • How is that possible ? are you using 32 or 63 bits ? – Baba Aug 05 '13 at 18:47
  • Same exact as the one above, so 64 bit and on a 64 bit system – voidraen Aug 05 '13 at 18:49
  • can anyone explain why `go` gives `-5340232216128654848` on some certain systems ? – Baba Aug 05 '13 at 18:50
  • 2
    Ah, the code above has an extra 0 in the long number. – voidraen Aug 05 '13 at 18:52
  • 3
    Why is this a community wiki? – jn1kk Aug 05 '13 at 20:28
  • 1
    @jsn It happens automatically when a question has more than 30 answers. (See [revisions of this question](http://stackoverflow.com/posts/18046347/revisions).) – flornquake Aug 05 '13 at 21:25
  • 3
    As @flornquake says, the question was made community wiki because it has 30 answers. From everything I see from the question and answers, this post is pretty much a poster-child for why that particular auto-trigger for Community Wiki was put in. – Andrew Barber Aug 06 '13 at 05:10
  • 1
    @Baba for such cases use maths instead of loops.. math aint hard brah – ShrekOverflow Aug 06 '13 at 12:39
  • PHP 5.3.10-1ubuntu3.7 with Suhosin-Patch (cli) on 64-bit Ubuntu 12.04 Precise and came out with: 500000000500000000 – user602525 Aug 06 '13 at 19:43
  • 4
    Why are people posting the same code sample converted to their favorite language? Are they not supposed to answer this question rather than post more useless snippets? – Kai Sellgren Aug 07 '13 at 10:55
  • @R.id.pandacoder Not to be selfish but did you see my [answer](http://stackoverflow.com/a/18055922/568109). – user568109 Aug 20 '13 at 18:14

36 Answers36

155

Python works:

>>> sum(x for x in xrange(1000000000 + 1))
500000000500000000

Or:

>>> sum(xrange(1000000000+1))
500000000500000000

Python's int auto promotes to a Python long which supports arbitrary precision. It will produce the correct answer on 32 or 64 bit platforms.

This can be seen by raising 2 to a power far greater than the bit width of the platform:

>>> 2**99
633825300114114700748351602688L

You can demonstrate (with Python) that the erroneous values you are getting in PHP is because PHP is promoting to a float when the values are greater than 2**32-1:

>>> int(sum(float(x) for x in xrange(1000000000+1)))
500000000067108992
dawg
  • 98,345
  • 23
  • 131
  • 206
  • Did you run this on 32 or 64 bit system ? – Baba Aug 04 '13 at 19:29
  • 64 bit build on OS X. Takes about 25 seconds. – dawg Aug 04 '13 at 19:32
  • Thanks for the info ... Let see if some can run this on 32 bit and see if the result is the same .. also test on 64 bit windows .. it works +1 – Baba Aug 04 '13 at 19:34
  • 4
    It should work regardless (32 vs 64 bit) since Python ints auto promote to arbitrary precision rather than overflow. Might take a while longer tho. – dawg Aug 04 '13 at 19:36
  • 3
    Python on any system will work in this case, since Python switches to long integers automatically if needed. And if that's not enough, it will switch to big integers as well. – Alok Singhal Aug 04 '13 at 19:37
  • 12
    @0x499602D2: That is kinda harsh. The OP himself voted it up. He asked specifically if this was similar problem on Python. Answer, no it is not. Code to show that it is not. WTH? – dawg Aug 04 '13 at 19:50
  • 10
    The Python example is overly long, just use sum(xrange(int(1e9)+1)) (....sum works on iterables) – Jay M Aug 04 '13 at 20:09
101

Your Go code uses integer arithmetic with enough bits to give an exact answer. Never touched PHP or Node.js, but from the results I suspect the math is done using floating point numbers and should be thus expected not to be exact for numbers of this magnitude.

zzzz
  • 87,403
  • 16
  • 175
  • 139
  • 46
    Yep. `If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.` - http://php.net/manual/en/language.types.integer.php – Nate Aug 04 '13 at 19:54
  • 3
    And in NodeJS (and JavaScript in general) all arithmetic operations (except bit operations) behave as if they were done with floating point numbers. Whether or not they actually are is an under-the-hood distinction subject to the decisions of individual JavaScript engines. – Peter Olson Aug 04 '13 at 21:02
  • 13
    In javascript's specification, there's no integer types. All numbers are floating points. – toasted_flakes Aug 04 '13 at 22:27
  • 8
    @grasGendarme There are. The ES5 spec [specifies various integer conversions](http://es5.github.io/#x9.4) and mandates that they be called [in bitwise shifts](http://es5.github.io/#x11.7), for example. That is to say *behind the scenes*, integers types are used in Javascript, but all the arithmetic operators convert their operands to floating point numbers before doing anything with them (barring compiler optimizations). – Peter Olson Aug 05 '13 at 01:40
  • 1
    Both SpiderMonkey (Firefox) and V8 (Chrome) also provide the extension `Math.imul` because even `((x|0)*(y|0))|0)` is not enough to provide integer semantics. The fact that integers are used is leaking pretty hard. – Esailija Aug 05 '13 at 07:19
  • [bitrayne](http://stackoverflow.com/questions/18046347/sum-of-1-to-1-000-000-000?noredirect=1#comment26435479_18046347) claims to have `-5340232216128654848` on 64 bits go1.1.1 ... Any ideas ? – Baba Aug 05 '13 at 18:53
  • 1
    @Baba: Good catch, there's one zero to many in the Go version `for i = 0 ; i <= 10000000000; i++ {` to produce the correct number `fmt.Println(sum) // 500000000500000000`. All of the other language examples have the correct `1000000000`. – zzzz Aug 05 '13 at 19:14
  • Isn't that supposed to depend on the machine's word length etc ? Why would a particular language want to do this in its own design ? – S.D. Aug 06 '13 at 06:10
  • Was was able to get a 32 bit system surprisingly go gave me `500000000067108992` ?? same as `PHP` – Baba Aug 12 '13 at 09:16
  • @Baba: I cannot find any reference from 'Was'. Can you please provide some pointer or link? – zzzz Aug 12 '13 at 09:29
  • I can it on my system .. i can give you screen shorts if you want – Baba Aug 12 '13 at 09:42
  • @Baba: Please use e.g. http://play.golang.org/ to share the code. It doesn't matter that it may not run there. – zzzz Aug 12 '13 at 09:53
  • @jnml [play](http://play.golang.org/) is 64 bits .. it does not have that issue .... try ruing my code on a 32 bit windows and see what i mean – Baba Aug 12 '13 at 12:28
  • @Baba: Use play only as a code pastie (in this case). Ad _"try runing my code"_: paste somewhere (eg. to play.golang.org) a full compilable code. Don't care about if it runs or not in play.golang.org. I'll try to run it locall of course (if I cannot see the error w/o running the code). – zzzz Aug 12 '13 at 12:55
  • 2
    [here is the code](http://play.golang.org/p/46a_d3dDG5) i guess its messed up because i used float64 and not int64 .. Just confirmed it has nothing to do with 32 or 64 bits – Baba Aug 12 '13 at 13:03
45

The reason is that the value of your integer variable sum exceeds the maximum value. And the sum you get is result of float-point arithmetic which involves rounding off. Since other answers did not mention the exact limits, I decided to post it.

The max integer value for PHP for:

  • 32-bit version is 2147483647
  • 64-bit version is 9223372036854775807

So it means either you are using 32 bit CPU or 32 bit OS or 32 bit compiled version of PHP. It can be found using PHP_INT_MAX. The sum would be calculated correctly if you do it on a 64 bit machine.

The max integer value in JavaScript is 9007199254740992. The largest exact integral value you can work with is 253 (taken from this question). The sum exceeds this limit.

If the integer value does not exceed these limits, then you are good. Otherwise you will have to look for arbitrary precision integer libraries.

Community
  • 1
  • 1
user568109
  • 47,225
  • 17
  • 99
  • 123
28

Here is the answer in C, for completeness:

#include <stdio.h>

int main(void)
{
    unsigned long long sum = 0, i;

    for (i = 0; i <= 1000000000; i++)    //one billion
        sum += i;

    printf("%llu\n", sum);  //500000000500000000

    return 0;
}

The key in this case is using C99's long long data type. It provides the biggest primitive storage C can manage and it runs really, really fast. The long long type will also work on most any 32 or 64-bit machine.

There is one caveat: compilers provided by Microsoft explicitly do not support the 14 year-old C99 standard, so getting this to run in Visual Studio is a crapshot.

CyberSkull
  • 796
  • 1
  • 7
  • 16
  • 3
    MSVC++ is a C++ compiler, and C++ got `long long` in the C++11 standard. It's been a MSVC++ and g++ extension for a few years, though. – MSalters Aug 05 '13 at 10:11
  • @MSalters Which edition of Visual Studio got this? I think the last version I used was the current one from 3 or 4 years ago. – CyberSkull Aug 05 '13 at 12:16
  • 1
    @MSalters So being a C++ feature it won't really help anyone compiling a straight C program. I never tried switching from C to C++, so I don't know if that workaround would actually work. – CyberSkull Aug 05 '13 at 12:23
  • 19
    And nicely, GCC or Clang with optimizations turn the whole loop into `movabsq $500000000500000000, %rsi` – Tor Klingberg Aug 05 '13 at 12:59
  • @TorKlingberg Which optimizations? – CyberSkull Aug 05 '13 at 13:04
  • @CyberSkull: VS2010, I think. Might have been VS2008, though. After all, they already had `__int64` so it was just a rename. – MSalters Aug 05 '13 at 13:21
  • 3
    Just `gcc -O3` or `clang -O3`. I don't know the name of the specific optimization. Basically the compiler notices that the result of the loop does not depend on any argument, and calculates it at compile time. – Tor Klingberg Aug 05 '13 at 13:25
  • At any optimization level `-O through -O3` it will `movabs $0x6f05b59f17f6500,%rsi` – Scotty Bauer Aug 05 '13 at 17:24
  • 1
    C99 long long has a minimum size of 64 bits and as far as I know is 64 bit on both 32-bit and 64-bit platforms. I haven't seen general support for quad or octo ints. – Devin Lane Aug 05 '13 at 17:37
  • VC has supported long long for a very long time - at least 2003 [according to MSDN](http://msdn.microsoft.com/en-us/library/cc953fe1\(v=vs.71\).aspx) and the "ll" printf syntax was [supported by 2005](http://msdn.microsoft.com/en-us/library/tcxf1dw6\(v=vs.80\).aspx). Additionally, note that `unsigned long long` should be printed with `%llu` . – Stephan T. Lavavej Aug 05 '13 at 18:56
  • Compilers provide by Microsoft doesn't support 14 years-old C99 std because C is too few used on Windows's applications. C++ is instead of. – The Mask Aug 05 '13 at 20:22
  • 1000000000 isn't treated as int? you dont must write 1000000000LL or 1000000000L? – Gelldur Aug 06 '13 at 21:38
  • @Gelldur I checked the assembly file, in this case (on Intel 64) it doesn't matter since one billion fits into an int just as well as a long. – CyberSkull Aug 07 '13 at 00:11
21

My guess is that when the sum exceeds the capacity of a native int (231-1 = 2,147,483,647), Node.js and PHP switch to a floating point representation and you start getting round-off errors. A language like Go will probably try to stick with an integer form (e.g., 64-bit integers) as long as possible (if, indeed, it didn't start with that). Since the answer fits in a 64-bit integer, the computation is exact.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
19

Perl script give us the expected result:

use warnings;
use strict;

my $sum = 0;
for(my $i = 0; $i <= 1_000_000_000; $i++) {
    $sum += $i;
}
print $sum, "\n";  #<-- prints: 500000000500000000
David G
  • 94,763
  • 41
  • 167
  • 253
Miguel Prz
  • 13,718
  • 29
  • 42
17

The Answer to this is "surprisingly" simple:

First - as most of you might know - a 32-bit integer ranges from −2,147,483,648 to 2,147,483,647. So, what happens if PHP gets a result, that is LARGER than this?

Usually, one would expect a immediate "Overflow", causing 2,147,483,647 + 1 to turn into −2,147,483,648. However, that is NOT the case. IF PHP Encounters a larger number, it Returns FLOAT instead of INT.

If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.

http://php.net/manual/en/language.types.integer.php

This said, and knowing that PHP FLOAT implementation is following the IEEE 754 double precision Format, means, that PHP is able to deal with numbers upto 52 bit, without loosing precision. (On a 32-bit System)

So, at the Point, where your Sum hits 9,007,199,254,740,992 (which is 2^53) The Float value returned by the PHP Maths will no longer be precise enough.

E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000000\"); echo number_format($x,0);"

9,007,199,254,740,992

E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000001\"); echo number_format($x,0);"

9,007,199,254,740,992

E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000010\"); echo number_format($x,0);"

9,007,199,254,740,994

This example Shows the Point, where PHP is loosing precision. First, the last significatn bit will be dropped, causing the first 2 expressions to result in an equal number - which they aren't.

From NOW ON, the whole math will go wrong, when working with default data-types.

•Is it the same problem for other interpreted language such as Python or Perl?

I don't think so. I think this is a problem of languages that have no type-safety. While a Integer Overflow as mentioned above WILL happen in every language that uses fixed data types, the languages without type-safety might try to catch this with other datatypes. However, once they hit their "natural" (System-given) Border - they might return anything, but the right result.

However, each language may have different threadings for such a Scenario.

dognose
  • 20,360
  • 9
  • 61
  • 107
15

The other answers already explained what is happening here (floating point precision as usual).

One solution is to use an integer type big enough, or to hope the language will chose one if needed.

The other solution is to use a summation algorithm that knows about the precision problem and works around it. Below you find the same summation, first with with 64 bit integer, then with 64 bit floating point and then using floating point again, but with the Kahan summation algorithm.

Written in C#, but the same holds for other languages, too.

long sum1 = 0;
for (int i = 0; i <= 1000000000; i++)
{
    sum1 += i ;
}
Console.WriteLine(sum1.ToString("N0"));
// 500.000.000.500.000.000

double sum2 = 0;
for (int i = 0; i <= 1000000000; i++)
{
    sum2 += i ;
}
Console.WriteLine(sum2.ToString("N0"));
// 500.000.000.067.109.000

double sum3 = 0;
double error = 0;
for (int i = 0; i <= 1000000000; i++)
{
    double corrected = i - error;
    double temp = sum3 + corrected;
    error = (temp - sum3) - corrected;
    sum3 = temp;
}
Console.WriteLine(sum3.ToString("N0"));
//500.000.000.500.000.000

The Kahan summation gives a beautiful result. It does of course take a lot longer to compute. Whether you want to use it depends a) on your performance vs. precision needs, and b) how your language handles integer vs. floating point data types.

linac
  • 532
  • 6
  • 14
  • @Baba It's the same as with Node.js/JavaScript in the OP. As to why 500000000067109000 vs. 500000000067108992 … no idea. – linac Aug 05 '13 at 12:09
  • Perhaps Baba is intrigued by the use of dots for thousand separators: english usually expects commas. You could also use underscores as a more neutral mean. – didierc Aug 05 '13 at 20:23
14

If you have 32-Bit PHP, you can calculate it with bc:

<?php

$value = 1000000000;
echo bcdiv( bcmul( $value, $value + 1 ), 2 );
//500000000500000000

In Javascript you have to use arbitrary number library, for example BigInteger:

var value = new BigInteger(1000000000);
console.log( value.multiply(value.add(1)).divide(2).toString());
//500000000500000000

Even with languages like Go and Java you will eventually have to use arbitrary number library, your number just happened to be small enough for 64-bit but too high for 32-bit.

Esailija
  • 138,174
  • 23
  • 272
  • 326
12

In Ruby:

sum = 0
1.upto(1000000000).each{|i|
  sum += i
}
puts sum

Prints 500000000500000000, but takes a good 4 minutes on my 2.6 GHz Intel i7.


Magnuss and Jaunty have a much more Ruby solution:

1.upto(1000000000).inject(:+)

To run a benchmark:

$ time ruby -e "puts 1.upto(1000000000).inject(:+)"
ruby -e "1.upto(1000000000).inject(:+)"  128.75s user 0.07s system 99% cpu 2:08.84 total
cgenco
  • 3,370
  • 2
  • 31
  • 36
11

I use node-bigint for big integer stuff:
https://github.com/substack/node-bigint

var bigint = require('bigint');
var sum = bigint(0);
for(var i = 0; i <= 1000000000; i++) { 
  sum = sum.add(i); 
}
console.log(sum);

It's not as quick as something that can use native 64-bit stuff for this exact test, but if you get into bigger numbers than 64-bit, it uses libgmp under the hood, which is one of the faster arbitrary precision libraries out there.

Eve Freeman
  • 32,467
  • 4
  • 86
  • 101
4

took ages in ruby, but gives the correct answer:

(1..1000000000).reduce(:+)
 => 500000000500000000 
Jauny
  • 950
  • 1
  • 8
  • 19
4

To get the correct result in php I think you'd need to use the BC math operators: http://php.net/manual/en/ref.bc.php

Here is the correct answer in Scala. You have to use Longs otherwise you overflow the number:

println((1L to 1000000000L).reduce(_ + _)) // prints 500000000500000000
3

There's actually a cool trick to this problem.

Assume it was 1-100 instead.

1 + 2 + 3 + 4 + ... + 50 +

100 + 99 + 98 + 97 + ... + 51

= (101 + 101 + 101 + 101 + ... + 101) = 101*50

Formula:

For N= 100: Output = N/2*(N+1)

For N = 1e9: Output = N/2*(N+1)

This is much faster than looping through all of that data. Your processor will thank you for it. And here is an interesting story regarding this very problem:

http://www.jimloy.com/algebra/gauss.htm

user2522001
  • 505
  • 3
  • 7
  • 11
    Do you think it might be possible to walk across every bridge across the Pregel in Kaliningrad, without crossing any bridge twice? Many people have tried and failed, but no-one has yet established that it is impossible. This seems like a challenge you would be uniquely qualified to solve. – jwg Aug 05 '13 at 11:36
3

This gives the proper result in PHP by forcing the integer cast.

$sum = (int) $sum + $i;
ck_
  • 3,353
  • 5
  • 31
  • 33
3

Common Lisp is one of the fastest interpreted* languages and handles arbitrarily large integers correctly by default. This takes about 3 second with SBCL:

* (time (let ((sum 0)) (loop :for x :from 1 :to 1000000000 :do (incf sum x)) sum))

Evaluation took:
  3.068 seconds of real time
  3.064000 seconds of total run time (3.044000 user, 0.020000 system)
  99.87% CPU
  8,572,036,182 processor cycles
  0 bytes consed

500000000500000000
  • By interpreted, I mean, I ran this code from the REPL, SBCL may have done some JITing internally to make it run fast, but the dynamic experience of running code immediately is the same.
postfuturist
  • 22,211
  • 11
  • 65
  • 85
  • Can be simplified as (time (loop for x from 1 to 1000000000 sum x)). I got ~5x speed by adding declaration: (time (locally (declare (optimize (speed 3) (safety 0))) (loop for i of-type fixnum from 1 to 1000000000 sum i of-type fixnum))) – huaiyuan Aug 05 '13 at 20:29
  • This is erroneous. Don't let you be blinded by the other languages! The correct way to write it in lisp is: (defun sum-from-1-to-n (n) (/ (* n (1+ n)) 2)) (time (sum-from-1-to-n 1000000000)) took 14 microseconds (0.000014 seconds) to run. During that period, and with 4 available CPU cores, 0 microseconds (0.000000 seconds) were spent in user mode 0 microseconds (0.000000 seconds) were spent in system mode --> 500000000500000000 – informatimago Aug 06 '13 at 08:26
  • @informatimago : It's not erroneous. I was copying the imperative loop style of the question and as many have pointed out, the question itself mentions there is an easier way to calculate. Chillax. – postfuturist Aug 06 '13 at 17:23
3

Racket v 5.3.4 (MBP; time in ms):

> (time (for/sum ([x (in-range 1000000001)]) x))
cpu time: 2943 real time: 2954 gc time: 0
500000000500000000
Keith Flower
  • 4,032
  • 25
  • 16
3

I don't have enough reputation to comment on @postfuturist's Common Lisp answer, but it can be optimized to complete in ~500ms with SBCL 1.1.8 on my machine:

CL-USER> (compile nil '(lambda () 
                        (declare (optimize (speed 3) (space 0) (safety 0) (debug 0) (compilation-speed 0))) 
                        (let ((sum 0))
                          (declare (type fixnum sum))
                          (loop for i from 1 to 1000000000 do (incf sum i))
                          sum)))
#<FUNCTION (LAMBDA ()) {1004B93CCB}>
NIL
NIL
CL-USER> (time (funcall *))
Evaluation took:
  0.531 seconds of real time
  0.531250 seconds of total run time (0.531250 user, 0.000000 system)
  100.00% CPU
  1,912,655,483 processor cycles
  0 bytes consed

500000000500000000
jdtw
  • 11
  • 2
3

Works fine in Rebol:

>> sum: 0
== 0

>> repeat i 1000000000 [sum: sum + i]
== 500000000500000000

>> type? sum
== integer!

This was using Rebol 3 which despite being 32 bit compiled it uses 64-bit integers (unlike Rebol 2 which used 32 bit integers)

draegtun
  • 22,441
  • 5
  • 48
  • 71
3

I wanted to see what happened in CF Script

<cfscript>
ttl = 0;

for (i=0;i LTE 1000000000 ;i=i+1) {
    ttl += i;
}
writeDump(ttl);
abort;
</cfscript>

I got 5.00000000067E+017

This was a pretty neat experiment. I'm fairly sure I could have coded this a bit better with more effort.

3

For the sake of completeness, in Clojure (beautiful but not very efficient):

(reduce + (take 1000000000 (iterate inc 1))) ; => 500000000500000000
Blacksad
  • 14,906
  • 15
  • 70
  • 81
3

ActivePerl v5.10.1 on 32bit windows, intel core2duo 2.6:

$sum = 0;
for ($i = 0; $i <= 1000000000 ; $i++) {
  $sum += $i;
}
print $sum."\n";

result: 5.00000000067109e+017 in 5 minutes.

With "use bigint" script worked for two hours, and would worked more, but I stopped it. Too slow.

Sly
  • 415
  • 2
  • 8
3

AWK:

BEGIN { s = 0; for (i = 1; i <= 1000000000; i++) s += i; print s }

produces the same wrong result as PHP:

500000000067108992

It seems AWK uses floating point when the numbers are really big, so at least the answer is the right order-of-magnitude.

Test runs:

$ awk 'BEGIN { s = 0; for (i = 1; i <= 100000000; i++) s += i; print s }'
5000000050000000
$ awk 'BEGIN { s = 0; for (i = 1; i <= 1000000000; i++) s += i; print s }'
500000000067108992
Daniel Hanrahan
  • 4,801
  • 7
  • 31
  • 44
2

Category other interpreted language:

Tcl:

If using Tcl 8.4 or older it depends if it was compiled with 32 or 64 bit. (8.4 is end of life).

If using Tcl 8.5 or newer which has arbitrary big integers, it will display the correct result.

proc test limit {
    for {set i 0} {$i < $limit} {incr i} {
        incr result $i
    }
    return $result
}
test 1000000000 

I put the test inside a proc to get it byte-compiled.

Community
  • 1
  • 1
Johannes Kuhn
  • 14,778
  • 4
  • 49
  • 73
2

For the PHP code, the answer is here:

The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.

vicentazo
  • 1,739
  • 15
  • 19
2

Harbour:

proc Main()

   local sum := 0, i

   for i := 0 to 1000000000
      sum += i
   next

   ? sum

   return

Results in 500000000500000000. (on both windows/mingw/x86 and osx/clang/x64)

vsz
  • 41
  • 1
  • 4
2

Erlang works:

from_sum(From,Max) ->
    from_sum(From,Max,Max).
from_sum(From,Max,Sum) when From =:= Max ->
    Sum;
from_sum(From,Max,Sum) when From =/= Max -> 
    from_sum(From+1,Max,Sum+From).

Results: 41> useless:from_sum(1,1000000000). 500000000500000000

Steve Moon
  • 99
  • 1
  • 4
2

Funny thing, PHP 5.5.1 gives 499999999500000000 (in ~ 30s), while Dart2Js gives 500000000067109000 (which is to be expected, since it's JS that gets executed). CLI Dart gives the right answer ... instantly.

Doru Moisa
  • 11
  • 1
  • 1
2

Erlang gives the expected result too.

sum.erl:

-module(sum).
-export([iter_sum/2]).

iter_sum(Begin, End) -> iter_sum(Begin,End,0).
iter_sum(Current, End, Sum) when Current > End -> Sum;
iter_sum(Current, End, Sum) -> iter_sum(Current+1,End,Sum+Current).

And using it:

1> c(sum).
{ok,sum}
2> sum:iter_sum(1,1000000000).
500000000500000000
Alex Moore
  • 3,415
  • 1
  • 23
  • 39
2

Smalltalk:

(1 to: 1000000000) inject: 0 into: [:subTotal :next | subTotal + next ]. 

"500000000500000000"
2

For completeness only.


In MATLAB there is no problem with automatic type selection:

tic; ii = 1:1000000; sum(ii); toc; ans

Elapsed time is 0.004471 seconds.
ans = 5.000005000000000e+11


And in F# interactive, automatic unit types give an overflow error. Assigning type int64 gives the correct answer:

seq {int64 1.. int64 1000000} |> Seq.sum

val it : int64 = 500000500000L

Notes:
Could use Seq.reduce (+) instead of Seq.sum without a noticeable change in efficiency. However, using Seq.reduce (+) with automatic unit type will give a wrong answer rather than an overflow error.
Computation time is <.5 seconds, but I am currently lazy and so I am not importing the .NET stopwatch class to get a more exact time.

user2307487
  • 243
  • 1
  • 8
2

A few answers have already explained why your PHP and Node.js code don't work as expected, so I won't repeat that here. I just want to point out that this has nothing to do with "interpreted vs compiled languages".

Perhaps this a problem of interpreted languages, and that's why it works in a compiled language like Go?

A "language" is merely a set of well-defined rules; an implementation of a language is what's either interpreted or compiled. I could take a language whose principal implementation is compiled (like Go) and write an interpreter for it (and vice-versa), but every program processed by the interpreter should produce identical output as running the program via the compiled implementation, and this output should be in accordance with the language's specification. The PHP and Node.js results are in fact in accordance with the languages' specifications (as some other answers point out), and this has nothing to do with the fact that the principal implementations of these languages are interpreted; compiled implementations of the languages by definition must also produce the same results.

A tangible example of all this is Python, which has both widely-used compiled and interpreted implementations. Running a translated version of your program in the interpreted implementation:

>>> total = 0 
>>> for i in xrange(1000000001):
...     total += i
... 
>>> print total
500000000500000000

must not, by the definition of Python, result in a different output than running it in the compiled implementation:

total = 0
for i in xrange(1000000001):
    total += i

print total
500000000500000000
arshajii
  • 127,459
  • 24
  • 238
  • 287
1

In ruby, these to functionally similar solutions (that return the correct answer) take significantly different amounts of time to complete:

$ time ruby -e "(1..1000000000).inject{|sum, n| sum + n}"
real    1m26.005s
user    1m26.010s
sys 0m0.076s

$ time ruby -e "1.upto(1000000000).inject(:+)"
real    0m48.957s
user    0m48.957s
sys 0m0.045s

$ ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-darwin10.8.0]
Steve Wilhelm
  • 6,200
  • 2
  • 32
  • 36
0

Javascript (and possibly PHP) represent all numbers as double, and round them for integer values. This means that they only have 53 bits of precision (instead of the 64 bits provided by int64 and a Java long), and will result in rounding errors on large values.

user2650994
  • 136
  • 5
0

As other people have pointed out, the fastest way to do this calculation (regardless of the language) is with a simple math function (instead of a CPU intensive loop):

number = 1000000000;
result = (number/2) * (number+1);

You would still need to solve any 32/64 bit integer/float issues, depending on the language, though.

Tom Chapin
  • 3,276
  • 1
  • 29
  • 18
0

And the ruby one's:

[15] pry(main)> (1..1000000000).inject(0) { |sum,e| sum + e }
=> 500000000500000000

Seems to get the right number.

Hartator
  • 5,029
  • 4
  • 43
  • 73