我只是試圖在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