我只是试图在JS中实现一个简单的RNG。JavaScript整数数学错误结果
发生了什么事是javascript评估119106029 * 1103515245
为131435318772912110
而不是131435318772912105
。我们知道这是错误的,因为两个奇数相乘并不能给出偶数。
任何人都知道这是怎么回事?我只想要一个可靠的可重复RNG,并且由于这些不正确的值,我无法得到与我的C实现相同的结果。
我只是试图在JS中实现一个简单的RNG。JavaScript整数数学错误结果
发生了什么事是javascript评估119106029 * 1103515245
为131435318772912110
而不是131435318772912105
。我们知道这是错误的,因为两个奇数相乘并不能给出偶数。
任何人都知道这是怎么回事?我只想要一个可靠的可重复RNG,并且由于这些不正确的值,我无法得到与我的C实现相同的结果。
根据ECMAScript标准,JavaScript中的所有数字都是(64位IEEE 754)浮点数。
但是,所有32位整数都可以精确地表示为浮点数。您可以使用适当的按位运算符将结果强制为32位,如下所示:
x = (a * b) >>> 0; // force to unsigned int32
x = (a * b) | 0; // force to signed int32
奇怪,但这是标准。
(顺便说一句该舍入行为是one of the most frequently reported "bugs"针对Firefox的JavaScript引擎看起来像它今年已报告3次,到目前为止...)
至于在JavaScript可重复的随机数,在V8基准测试使用此:
// To make the benchmark results predictable, we replace Math.random
// with a 100% deterministic alternative.
Math.random = (function() {
var seed = 49734321;
return function() {
// Robert Jenkins' 32 bit integer hash function.
seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
seed = ((seed^0xc761c23c)^(seed >>> 19)) & 0xffffffff;
seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
seed = ((seed + 0xd3a2646c)^(seed << 9)) & 0xffffffff;
seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
seed = ((seed^0xb55a4f09)^(seed >>> 16)) & 0xffffffff;
return (seed & 0xfffffff)/0x10000000;
};
})();
IIRC我在我的应用程序([htmltetris.com](http://htmltetris.com))中使用了这个或者Robert Jenkins PRNG的其他变体 – 2014-07-15 15:12:54
当javascript中的整数太大而不适合32位值时,某些浏览器会将其转换为浮点。由于浮点的值只能保存到有限的精度,所以在大值时可能会出现一些舍入。
尽管结果对于最后两位是正确的。如果它只是截断高位,但我想要的只是结果的低32位,这是有道理的。我如何获得? – 2010-08-06 22:10:29
@Steven:Javascript实际上并没有整数类型,在这种情况下,您会看到浮点数的精度损失。而那些保留数字的“上半部分”,而不是低位(像整数乘法那样)。 – Joey 2010-08-06 22:12:14
@Johannes:好的,这很有道理。不知道如何解决这个问题... – 2010-08-06 22:15:01
如果在C/C++(双)中完成,最后的数字将是... 112 而不是105(这是正确的)。如果执行'长双', 结果将如预期的那样(... 105)。所以它看起来像是 Javascript解释器在内部将数字转换为8字节双倍的 ,进行计算并做了一些未知的取整 ,这导致比C/C++标准 双重计算稍微好一点的结果。
GCC 4.5:
int main(int argc, char** argv)
{
long double a = 119106029;
long double b = 1103515245;
long double c = a * b;
printf("%.Lf\n", c);
return 0;
}
结果:
131435318772912105
预计:
131435318772912105
所以我看不出在Javascript的机会,而不 援助BIGNUM库(如果有的话)。
问候
RBO
如果我是你,我会问:为什么你需要摆在首位乘这样庞大的数字?如果不使用这种方法,这可能是一种做你想做的事的方法。 除非它的一些科学问题领域,你可能会有设计错误。 – Nobody 2010-08-06 22:12:09
只是制作最简单的随机数发生器。大数乘以2 ** 32加一个常数mod。我只对最后几位感兴趣!但他们错了。为什么? – 2010-08-06 22:13:34
'Math.random()* 100000(00 .....)'是不够的时候!? – Matt 2010-08-06 22:16:38