代码之家  ›  专栏  ›  技术社区  ›  Steven Lu

javascript整数数学错误结果

  •  3
  • Steven Lu  · 技术社区  · 14 年前

    我只是想在JS中实现一个简单的RNG。

    发生的是javascript评估 119106029 * 1103515245 成为 131435318772912110 而不是 131435318772912105 . 我们知道这是错误的,因为两个奇数相乘不能得到一个偶数。

    有人知道怎么回事吗?我只想要一个可靠的可重复的RNG,因为这些不正确的值,我无法得到与我的C实现相匹配的结果。

    3 回复  |  直到 14 年前
        1
  •  17
  •   Jason Orendorff    14 年前

    根据EcmaScript标准,javascript中的所有数字都是(64位IEEE754)浮点数。

    然而,所有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" 反对火狐的javascript引擎。看来今年到目前为止已经报道了三次了……)

    对于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;
      };
    })();
    
        2
  •  3
  •   Scharrels    14 年前

    当javascript中的整数太大而不能容纳32位值时,某些浏览器会将其转换为浮点值。由于浮点值的保存精度有限,因此大值上可能会出现一些舍入。

        3
  •  1
  •   rubber boots    14 年前

    如果在C/C++(双)中完成,最后的数字将是…112。 而不是105(正确)。如果使用“长双精度”, 结果与预期一致(…105)。所以看起来像 javascript解释器将数字转换为8字节双精度 在内部,进行计算并进行一些未知的取整 这导致了比C/C++标准稍好的结果。 双重计算。

    海湾合作委员会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
    

    所以我看不到在没有 Bignum图书馆的帮助(如果有的话)。

    当做

    RBO