在解释型语言上使用非常大的整数时出现意外结果

我试图得到的总和,但我在PHP和Node.js得到了有趣的结果。1 + 2 + ... + 1000000000

菲律宾比索

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

节点.js

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

正确答案可以使用以下公式计算

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

正确答案=500000000500000000,所以我决定尝试另一种语言。

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

但它工作正常!那么我的PHP和Node.js代码有什么问题呢?

也许这是解释型语言的问题,这就是为什么它可以在像Go这样的编译语言中工作的原因?如果是这样,其他解释型语言(如Python和Perl)会有同样的问题吗?


答案 1

Python的工作原理:

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

艺术

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

Python的自动提升为支持任意精度的Python。它将在 32 位或 64 位平台上生成正确的答案。intlong

这可以通过将2提高到远远大于平台位宽度的功率来显示:

>>> 2**99
633825300114114700748351602688L

你可以证明(使用 Python)你在 PHP 中获得的错误值是因为 PHP 在值大于 2**32-1 时会提升为浮点数:

>>> int(sum(float(x) for x in xrange(1000000000+1)))
500000000067108992

答案 2

您的 Go 代码使用整数算术,其中包含足够的位来给出确切的答案。从未接触过PHP或Node.js,但从结果来看,我怀疑数学是使用浮点数完成的,因此应该期望对于这种大小的数字不是精确的。


推荐