32位JavaScript数字如何由逐位运算转换回64位数

时间:2013-03-20 07:26:35

标签: javascript bit-manipulation

我试图理解JavaScript中的逐位操作是如何工作的,更具体地说是如何将按位操作产生的32位数转换回64位JavaScript数。当设置32位数字中的最左位以及操作溢出时,我得到一些奇怪的结果。

例如,通过以下操作:

0x01 << 31

如果数字长度为32位,通常会导致0x80000000。但是当JavaScript将此数字转换回64位值时,它会使用1填充最左边的32位,从而产生值FFFFFFFF80000000

类似地,当左移32位,因此溢出32位整数时,操作为:

0x02 << 32

数字会溢出,结果值应为0x00。但生成的JavaScript编号为0x02

JavaScript是否有任何特定的规则用于我不知道的按位操作?我知道所有的位操作都是用32位整数执行的,并且JavaScript编号是64位双精度浮点数,但我无法理解在两者之间进行转换时额外填充的来源。

2 个答案:

答案 0 :(得分:1)

  1. 按位运算符的结果是 signed int32,符号位在转换回Numbers时会传播。

  2. 您的移位不能超过31位:

  3. Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.

    也就是说,x<<32x<<0相同。

答案 1 :(得分:0)

在JavaScript中,所有数字都使用53位表示。 JavaScript使用浮点表示在内部存储所有数字,这意味着整数存储为浮点数(尾数有53位)。这篇博客文章很好地阅读了这个主题。

因此,对于53位,我们可以表示最大值2 ^ 53 = 9007199254740992。

与其他语言(如C,C#)不同,您不能使用右移和AND二进制运算从JavaScript中的53位数中提取低32位和高21位。

原因是当我们对任何数字应用二元运算符时 - JavaScript首先将该数字转换为32位有符号数,应用二进制运算并返回结果。这意味着任何位于高于32位的位都将被丢弃。

我使用以下方法从正数<= 2 ^ 53中提取较高(21位)和较低(32位)的部分。

var bigNumber = Math.pow(2, 53); // 9007199254740992
var bigNumberAsBinaryStr = bigNumber.toString(2); // '100000000000000000000000000000000000000000000000000000'
// Convert the above binary str to 64 bit (actually 52 bit will work) by padding zeros in the left
var bigNumberAsBinaryStr2 = '';
for (var i = 0; i < 64 - bigNumberAsBinaryStr.length; i++) {
    bigNumberAsBinaryStr2 += '0';
};

bigNumberAsBinaryStr2 += bigNumberAsBinaryStr;

var lowInt = parseInt(bigNumberAsBinaryStr2.substring(0, 32), 2);
var highInt = parseInt(bigNumberAsBinaryStr2.substring(32), 2);

要回答有关转换回64位的问题,请参阅以下内容:

Assert((lowInt * Math.pow(2, 32) + highInt) === bigNumber);