具有大整数的按位运算

时间:2011-07-27 16:08:04

标签: javascript integer bit-manipulation

我正在实现BER压缩整数的解码,最近我发现了与大整数的按位运算相关的奇怪的JavaScript行为。

E.g:

var a = 17516032;          // has 25 bits
alert(a << 7)              // outputs -2052915200
alert(a * 128)             // outputs  2242052096
alert(2242052096 >> 16)    // outputs -31325
alert(2242052096 / 65536)  // outputs  34211

虽然第一种解决方法(乘法而不是左移)是可以接受的,但第二种不是。

为什么会这样?怎么忍受呢?

4 个答案:

答案 0 :(得分:7)

二进制文件中的

1751603200000001000010110100011000000000。向左移动7可以得到10000101101000110000000000000000。这等于two's complement中的-2052915200(几乎所有计算机都代表负数)。

>>是签名的右移。这意味着最左边的位(确定一个数字的符号)将被移到左侧。

e.g。

1100 >> 2 == 1111
0111 >> 2 == 0001

如果你想做一个无符号移位(忽略符号位),使用>>>将零填充位串的左端。

答案 1 :(得分:3)

按位运算符用于32位整数,而乘法和除法用于浮点数。

当移位数字时,它在操作之前从浮点数转换为32位整数,并在操作之后转换回浮点数。数字2242052096设置了第32位,因此在转换为32位整数时为负数。

>>右移运算符不会更改值的符号,即从左侧移入的位具有与符号位相同的值。使用>>>右移运算符来改为零位。

参考:MDN: Bitwise operators

答案 2 :(得分:2)

(2242052096 / 65536) == (2242052096 >>> 16)

注意不同的转变。

答案 3 :(得分:1)

Javascript通常将数字表示为(双精度)浮点数。

几乎所有按位运算都转换为带符号的32位整数,执行它们要做的任何事情,然后在转换回来时将结果视为带符号的32位整数。

异常是>>>,它在转换回来时将结果视为无符号 32位整数。

所以:

  • 只需使用>>>代替>>;
  • 即可使右移改变工作
  • a * 128给出了预期的答案,因为它从未首先转换为带符号的32位整数 - 它只是一个浮点乘法;
  • a << 7给出了意想不到的答案,因为它被转换为带符号的32位整数,然后将1移入符号位,从而产生负的带符号32位值。

没有<<<,但如果您想将左移作为班次,可以使用

(a << 7) >>> 0

获得预期的答案(>>> 0有效地将带符号的32位值转换为无符号的32位值。)