在JavaScript中,是否可以使用类型化数组将4个Uint8转换为Uint32?

9

我正在一个项目中进行一些位操作,我想知道内置的类型化数组是否可以帮我省去一些麻烦,甚至能否为我提供一些性能上的优势。

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 是负数,这很奇怪——显然不太符合变量名称所建议的“无符号”...

如果我把二进制八位数拼起来并解析它,就会得到补码表示的正数。

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

console.log(uint32)
// 2155971203 

毫不奇怪,我可以反转过程以得到每个正确的值,但我不明白为什么第一种方法是负数而第二种方法是正数。

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


你无法从一个UNSIGNED int32变量获得负数! - Jaromanda X
@JaromandaX 我在我的问题中间确实评论了那个... :\ - Mulan
为什么不尝试使用Int32Array呢? - Jaromanda X
1
你可以使用通常的 >>> 0 技巧来重新解释上面的负数为无符号数。 - harold
1个回答

9
使用DataView是处理这个问题的最佳方式 - 这样你就可以指定要获取的值的字节序 - 你的代码正在使用bigendian值来表示int32。
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]

返回一个有符号整数是因为位运算符(<<|)将值强制转换为有符号32位值。


这正是我正在寻找的 ^_^ - Mulan
因为这是一个好答案,我在使用了两年后仍然在用,哈哈。 - NoobTW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接