我有一个数组:
[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]中的最后一个值为0
或1
时。将最后一个值设置为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。我在做什么错了?
答案 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">