4

I performed the same addition in PHP and NodeJS. PHP calculated correctly upto 1 billion iterations, but NodeJS calculated correctly only up to 100 million iterations.

This is the PHP code:

<?php
$start_time = time();
$j = 0;
for ($i = 0; $i <= 1000000000; $i++) {
    $j += $i;
}
$end_time = time();
echo "Time Taken: " . ($end_time - $start_time);
echo "\n";
echo "i: " . $i;
echo "\n";
echo "j: " . $j;
echo "\n";
?>

Which returned the following output:

Time Taken: 15
i: 1000000001
j: 500000000500000000

This is the NodeJS code:

var epoch = require('epoch.js');
var start_time = epoch().format('ss');
var i;
var j = 0;
for (i = 0; i <= 1000000000; i++) {
    j += i;
}
var end_time = epoch().format('ss');
var time_taken = end_time - start_time;
console.log("Time Taken: " + time_taken + " \ni: " + i + "\nj: " + j);

Which returned the following output:

Time Taken: 1 
i: 1000000001
j: 500000000067109000

Why is the j variable wrong in NodeJS?

Edit:

As pointed out by @SalmanA (and confirmed by me) I would further like to ask why the max integer limit stays same for Javascript on different processors, but changes for PHP?

Turab
  • 134
  • 1
  • 14
  • http://www.javascripter.net/faq/accuracy.htm this article describes why js is inaccurate and also how you go around. – nichtgian Jan 17 '18 at 07:06
  • PHP floating point numbers are subject to same limitations as those for JavaScript number. Why PHP produces 500000000500000000 is beyond me... I get different result. – Salman A Jan 17 '18 at 07:10
  • With your PHP code I get `500000000067109000` by setting [`precision`](http://php.net/manual/en/ini.core.php#ini.precision) to 17. – Salman A Jan 17 '18 at 07:23
  • That is actually another interesting question: It seems Javascript conforms to a fixed limit whereas for PHP the limit changes with hardware. Thanks for pointing it out @SalmanA – Turab Jan 17 '18 at 07:25
  • @Turab PHP _typically_ uses the same floating point number format that JavaScript uses (IEEE 754) so both have same characteristics and same problems. If your PHP script displays 500000000500000000 then something is peculiar about your PHP setup. – Salman A Jan 17 '18 at 07:35
  • @SalmanA I checked this same piece of code on two very different machines with very different PHP setups, yet returning the same output. Details of the machines are: Machine 1: Intel Core i5-6440HQ CPU @ 2.60GHz - 8GB DDR4 RAM - PHP 7.1 --- Machine 2: Intel Xeon E3-1246V3 - 4GB DDR3 - PHP 5.6 – Turab Jan 17 '18 at 07:49
  • In JavaScript all numbers are _defined_ to be 64-bit IEEE-754 doubles. In PHP, they're not - it's architecture dependent. – Alnitak Jan 17 '18 at 11:02

2 Answers2

3

Since you changed the intent of question I felt like reopening it.

In JavaScript, there are no integers or floats, just Number, represented using IEEE 754-2008 64-bit (double-precision) format. One of the characteristics of this format is that all "integers" between −9007199254740991 and 9007199254740991 can be represented accurately. Numbers outside this range are approximated. Simple example:

> 9007199254740993
< 9007199254740992

Your Node.js code produces a value that is larger than Number.MAX_SAFE_INTEGER which is why the result is approximate instead of accurate.


In PHP, you have integers and floats. However:

  • The size of integer datatype is not the same across all platforms
    • PHP x64 uses 8-byte integers* (-9223372036854775808 ... 9223372036854775807)
    • PHP x86 uses 4-byte integers (-2147483648 ... 2147483647)
    • PHP seems to use IEEE 754-2008 64-bit floats, same as JavaScript
  • PHP changes the datatype of variable from integer to float in case of overflow

Your sample program, when run on PHP x64 ends up with $j = int(500000000500000000) which is less than the value of PHP_INT_MAX so conversion to float (and loss of accuracy) does not happen.

The same code, when run on PHP x86 converts the variable to a float value once it becomes greater than PHP_INT_MAX and therefore you will end up with $j = float(5.0000000006710899E+17)**.


* Not on Windows though
** you need to set precision to the maximum value

Salman A
  • 262,204
  • 82
  • 430
  • 521
2

javascript Number.MAX_SAFE_INTEGER is 9007199254740991

Rotimi
  • 4,783
  • 4
  • 18
  • 27
Cr.
  • 886
  • 7
  • 12