如何将值打包为有符号的32个整数

时间:2018-11-29 14:41:20

标签: javascript c bitwise-operators

我有一个数组:

[43, 44, 45, 46, 47, 2]

我需要将其转换为一个32位无符号整数。因此,前5个值每个使用6位,最后一个值使用2个位。

C 上,此代码如下:

 varToPack = (array[0] &0x3F) +
              ( (array[1]<<6) &0x3F) +
              ( (array[2]<<12) &0x3F) +
              ( (array[3]<<18) &0x3F) +
              ( (array[4]<<24) &0x3F) +
              ( (array[5]<<30) &3)

我想在JS上做同样的事情,并且可以正常工作:

let varToPack = arr[0]+
(arr[1]<<6)+
(arr[2]<<12)+
(arr[3]<<18)+
(arr[4]<<24)+
(arr[5]<<30);

但是仅当array [5]中的最后一个值为01时。将最后一个值设置为2后,得到负数。因此,根据此答案:

Bitwise operations on 32-bit unsigned ints?

我做了以下修改:

let varToPack = arr[0]+
(arr[1]<<6)+
(arr[2]<<12)+
(arr[3]<<18)+
(arr[4]<<24)+
((arr[5]<<30)>>>0);

这有效,但是总的来说,它返回值收集然后是 2147483648 ,因为我没有使用&0x3F来使数字大于6位。

但是当我这样做时:

let varToPack = (arr[0]&0x3F)+
                ((arr[1]<<6)&0x3F)+
                ((arr[2]<<12)&0x3F)+
                ((arr[3]<<18)&0x3F)+
                ((arr[4]<<24)&0x3F)+
                (((arr[5]<<30)>>>0)&3);

它返回0。我在做什么错了?

2 个答案:

答案 0 :(得分:1)

不起作用的原因:

let varToPack = (arr[0]&0x3F)+
                ((arr[1]<<6)&0x3F)+
                ((arr[2]<<12)&0x3F)+
                ((arr[3]<<18)&0x3F)+
                ((arr[4]<<24)&0x3F)+
                (((arr[5]<<30)>>>0)&3);

是因为您首先移位了每个值,然后然后执行逻辑与。由于所需的位已从AND指定的位置移出,因此所有内容都会被屏蔽掉。您要屏蔽这些值,然后然后进行移位。另外,请使用逻辑OR而不是加法,因为这可以更准确地反映您的实际工作。

let varToPack = (a[0] &0x3F) |
              ( (a[1] & 0x3f) <<6) |
              ( (a[2] & 0x3f) <<12) |
              ( (a[3] & 0x3f) <<18) |
              ( (a[4] & 0x3f) <<24) |
              (( (a[5] & 0x3) <<30) >>> 0);

对于负值,JavaScript对32位带符号的值执行所有按位运算(然后将其结果转换为64位浮点数),因此结果为负也就不足为奇了。

但是,存储的值将出现在结果变量中。如果您从有问题的值中提取出位,则将获得原始值:

let b = [];
b[0] = varToPack & 0x3f;
b[1] = (varToPack >>> 6) & 0x3f;
b[2] = (varToPack >>> 12) & 0x3f;
b[3] = (varToPack >>> 18) & 0x3f;
b[4] = (varToPack >>> 24) & 0x3f;
b[5] = (varToPack >>> 30) & 0x3;

答案 1 :(得分:1)

不幸的是,JavaScript中的按位运算符是limited to 32-bit signed integers

您不能将输入“打包”为32位有符号整数,因为2 * 2 30 超过了它。正号最大32位整数是2 31 -1。

如果您想将其打包为64位整数,可以将6th元素乘以2 30 来避免32位有符号整数溢出:

let arr=[43, 44, 45, 46, 47, 2];

let varToPack =  arr[0] + 
                (arr[1]<<6) +
                (arr[2]<<12) +
                (arr[3]<<18) +
                (arr[4]<<24) +
                (arr[5]*(1<<30));

document.getElementById("result").innerHTML = varToPack;
Result: <span id="result">