代码之家  ›  专栏  ›  技术社区  ›  Josh Weinstein

如果位移位过多,javascript数字将重置为0

  •  3
  • Josh Weinstein  · 技术社区  · 7 年前

    所以我试着用javascript编写一些函数来转换和操作数字位。但是,我在控制台中发现了以下行为

    > var a = 1;
    undefined
    > a <<= 3
    8
    > a <<= 55
    67108864
    > a <<= 40
    0
    

    我的问题是,如果这个值在某个点以上变大,为什么这个数字会回到零?在其他语言(如python)中,数字只是不断变大,或者使用符号来保存数字的值。或者,显示溢出错误。为什么javascript只是将数字重置为零?

    2 回复  |  直到 7 年前
        1
  •  4
  •   Nick is tired Boris    7 年前

    根据 the documentation 以下内容:

    移位运算符将其操作数按大端顺序转换为32位整数,并返回与左操作数类型相同的结果。右操作数应小于32,但如果不使用低位5位的话。

    所以在你的情况下 55 (0x110111) 40 (0x101000) 你有点走投无路了 23 (0x10111) 8 (0x01000) 分别是:

    > var a = 1;
    undefined
    > a <<= 3
    8
    > a <<= 23
    67108864
    > a <<= 8
    0
    

    请注意,虽然这些与您所写的不同,但答案与您为什么得到0相同,请考虑以下几点:

    > var a = 1;
    undefined
    > a <<= 3 + 23
    67108864    // 0x000[00000100000000000000000000000000]
    > a <<= 8
    0           // 0x100[00000000000000000000000000000000]
    

    方括号表示实际用于确定数字值的值,左边的部分被丢弃。如您所见,您已经将1从数字的左边一路位移,结果0被移到了左边。

    注意下面的代码片段,达到32移位标记后,所有结果都为0:

    var a = 1;
    for(var i = 1; i < 40; i++){
        a <<= 1;
        console.log(i, a);
    }
        2
  •  0
  •   apsillers    7 年前

    左位移位的语义在 ES2018 section 12.9.3.1 是的。要理解的主要问题是,左操作数被转换为32位有符号整数,结果也是32位整数。

    在左位移位中,左操作数按右操作数(最低5位)指定的位数移位。

    例如, 1 << 3 执行二进制转换

    00000000000000000000000000000001
    

    00000000000000000000000000001000
    

    那就是 8 是的。

    手术 67108864 << 40 (与操作相同 67108864 << 8 )正在32位数字上操作

    00000100000000000000000000000000
    

    当你把这个调高8位的时候

    10000000000000000000000000000000000
    

    这是35位。由于位移位的输出总是一个有符号的32位数字,所以它会丢失其最高位,从而导致较低的32位表示 0 是的。