JavaScript 整数数学结果不正确
我只是想用 JS 实现一个简单的 RNG。
发生的情况是 javascript 将 119106029 * 1103515245
计算为 131435318772912110
而不是 131435318772912105
。我们知道这是错误的,因为两个奇数相乘不会得到偶数。
有人知道怎么回事吗?我只想要一个可靠的可重复 RNG,由于这些不正确的值,我无法获得与我的 C 实现相匹配的结果。
I am just trying to implement a simple RNG in JS.
What's happening is javascript evaluates 119106029 * 1103515245
to be 131435318772912110
rather than 131435318772912105
. We know it's wrong since two odd numbers multiplied does not give an even number.
Anyone know what's up? I just want a reliable repeatable RNG, and because of these incorrect values I can't get results to match up with my C implementation of the same thing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据 ECMAScript 标准,默认情况下 JavaScript 中的所有数字都是(64 位 IEEE 754)浮点数。
然而,所有 32 位整数都可以精确地表示为浮点数。您可以使用适当的按位运算符将结果强制为 32 位,如下所示:
很奇怪,但这就是标准。
(顺便说一句,这种舍入行为是最常报告的“错误”之一 Firefox 的 JavaScript 引擎今年到目前为止已被报道 3 次...)
如果您想要真正的整数数学,您可以使用
BigInt
值,这是一种不同类型的数字,用编写>n
结尾:这是一个相对较新的 JS 功能,在旧浏览器中可能无法实现。
至于 JavaScript 中的可重现随机数,V8 基准测试使用以下内容:
Per the ECMAScript standard, all numbers in JavaScript are (64-bit IEEE 754) floating-point numbers by default.
However all 32-bit integers can be exactly represented as floating-point numbers. You can force a result to 32 bits by using the appropriate bitwise operator, like this:
Weird, but that's the standard.
(Incidentally this rounding behavior is one of the most frequently reported "bugs" against Firefox's JavaScript engine. Looks like it's been reported 3 times so far this year...)
If you want real integer math, you can use
BigInt
values, a different type of number, written with ann
at the end:This is a relatively recent JS feature, and may not be implemented in old browsers.
As for reproducible random numbers in JavaScript, the V8 benchmark uses this:
当 javascript 中的整数太大而无法容纳 32 位值时,某些浏览器会将其转换为浮点数。由于浮点值仅保存为有限的精度,因此大值可能会发生一些舍入。
When an integer in javascript is too big to fit in a 32 bit value, some browsers will convert it to a floating point. Since the value of floating points is only save to a limited precision, some rounding can occur on big values.
如果在 C/C++(双精度)中完成,最后的数字将是 ...112
而不是 105(这是正确的)。如果使用“long double”执行,
结果将如预期(...105)。所以看起来像
Javascript 解释器将数字转换为 8 字节双精度
在内部进行计算并进行一些未知的舍入
这导致比 C/C++ 标准稍好的结果
双重计算。
GCC 4.5:
结果:
预期:
所以如果没有
BIGNUM 库的帮助(如果有)。
问候
rbo
If done in C/C++ (double), the last numbers will be ...112
instead of 105 (which is correct). If performed with 'long double',
the result will be as expected (...105). So it looks like the
Javascript interpreter converts the numbers to 8-byte-double
internally, does the calculation and does some unknown rounding
which leads to a marginally better result than the C/C++ standard
double calculation.
GCC 4.5:
Result:
Expected:
So I don't see a chance in Javascript without the
aid of a BIGNUM library (if any).
Regards
rbo
随着 BigInt 的到来,您现在可以准确地执行这些计算:
With the arrival of BigInt, you can now perform these calculations with accuracy: