如何将位操作产生的32位JavaScript数字转换回64位数字?



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

例如,使用如下操作:

0x01 << 31
如果数字是32位长,

通常会导致0x80000000。但是当JavaScript将这个数字转换回64位值时,它会在最左边的32位加上1,从而得到值FFFFFFFF80000000

类似地,当左移32位,从而溢出一个32位整数时,使用操作:
0x02 << 32

数值会溢出,结果值应该是0x00。但是结果的JavaScript编号是0x02

是否有任何特定的规则,JavaScript使用的位操作,我不知道?我知道所有的位操作都是用32位整数执行的,JavaScript数字是64位双精度浮点数,但是我不明白在两者之间转换时额外的填充来自哪里。

  1. 位运算符的结果是带符号的 int32,符号位在转换回数字时传播。

  2. 不能移动超过31位:

让shiftCount为除去rnum中最不重要的5位以外的所有位的结果,即计算rnum &0 x1f。

x<<32x<<0相同

在JavaScript中,所有数字都使用53位表示。JavaScript使用浮点表示在内部存储所有数字,这意味着整数被存储为浮点数(尾数有53位)。这篇博文是关于这个主题的一篇好文章。

所以用53位我们可以表示最大2^53 = 9007199254740992。

与C、c#等其他语言不同,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);

最新更新