是否可以使用JavaScript中的类型数组从4x Uint8转换为Uint32?

时间:2016-09-10 04:17:58

标签: javascript bit-manipulation bitwise-operators typed-arrays

我在项目中做了一些按位操作,我想知道内置的类型数组是否会让我感到头痛,甚至可能会给我带来一点性能提升。

let bytes = [128, 129, 130, 131]
let uint32 = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]
//=> -2138996093

我可以使用类型化数组来获得相同的答案吗?

// not actually working !
let uint8bytes = Uint8Array.from(bytes)
let uint32 = Uint32Array.from(uint8bytes)[0]
//=> ideally i'd get the same value as above: -2138996093

附带问题:

我发现奇怪的是上面的uint32是否定的 - 显然不是很...... 无符号因为var的名字暗示......

如果我将二进制八位字节混合并解析它,我会得到免费的肯定答案

&#13;
&#13;
//         128          129          130          131
let bin = '10000000' + '10000001' + '10000010' + '10000011'
let uint32 = Number.parseInt(bin,2)

console.log(uint32)
// 2155971203 
&#13;
&#13;
&#13;

毫不奇怪我可以改变过程以获得正确的价值,但我不明白为什么程序1是否定的,但程序2是正面的。

&#13;
&#13;
let a = -2138996093;
let b = 2155971203;

// two's compliment, right?
console.log(a.toString(2)) // -1111111011111100111110101111101
console.log(b.toString(2)) // 10000000100000011000001010000011

console.log(a >> 24 & 255) // 128
console.log(a >> 16 & 255) // 129
console.log(a >> 8 & 255)  // 130
console.log(a >> 0 & 255)  // 131

console.log(b >> 24 & 255) // 128
console.log(b >> 16 & 255) // 129
console.log(b >> 8 & 255)  // 130
console.log(b >> 0 & 255)  // 131
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:4)

处理此问题的最佳方法是使用DataView - 这样您就可以指定要获取的值的字节顺序 - 您的代码使用了int32的bigendian值

let bytes = [128, 129, 130, 131];
let uint8bytes = Uint8Array.from(bytes);
let dataview = new DataView(uint8bytes.buffer);
let int32le = dataview.getInt32(0, true); // second parameter truethy == want little endian
let int32be = dataview.getInt32(0); // second parameter absent or falsey == want big endian
console.log(int32le); // -2088599168
console.log(int32be); // -2138996093

原因

let uint32 = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]

返回一个SIGNED int,即按位运算符(<<|)将值强制转换为带符号的32位值