javascript:不使用按位运算将二进制字符串转换为 UInt32 大端
javascript: convert binary string to UInt32 big-endian without use of bitwise operations
我正在编写一个共享代码库,我们有 'no bitwise operations' 的 linting 规则。但是,我正在使用一个简短的实用函数将二进制字符串转换为 unsigned int 32,big-endian。效果很好:
// converts a four-character string into a big endian 32-bit unsigned integer
stringAsUInt32BE(binString) {
return (binString.charCodeAt(0) << 24) + (binString.charCodeAt(1) << 16) +
(binString.charCodeAt(2) << 8) + binString.charCodeAt(3);
};
如果没有按位运算,我怎么能做到这一点?谢谢!
您可以使用具有 2 个不同视图的 ArrayBuffer。使用 Uint8Array
写入字节并使用 DataView
指定大端顺序读出一个值,如下所示:
stringAsUInt32BE(binString) {
var buffer = new ArrayBuffer(4);
var uint8View = new Uint8Array(buffer);
uint8View[0] = binString.charCodeAt(0);
uint8View[1] = binString.charCodeAt(1);
uint8View[2] = binString.charCodeAt(2);
uint8View[3] = binString.charCodeAt(3);
return new DataView(buffer).getUint32(0, false); // false for big endian
}
当不支持类型化数组时,使用位操作在旧版浏览器上效果更好。
您可以将 << x
替换为 * Math.pow(2, x)
。
这两个语句的主要区别在于非常大或负输入的行为 x
,例如按位运算符将其操作数转换为二补数,而其他算术运算符则不会。
// converts a four-character string into a big endian 32-bit unsigned integer
function stringAsUInt32BE(binString) {
return binString.charCodeAt(0) * 16777216 + binString.charCodeAt(1) * 65536 + binString.charCodeAt(2) * 256 + binString.charCodeAt(3);
}
console.log(stringAsUInt32BE('\xFF\xFF\xFF\xFF')); // 4294967295
console.log(stringAsUInt32BE('\x00\x00\x00\x00')); // 0
注意 stringAsUInt32BE('\xFF\xFF\xFF\xFF')
的行为:您的原始函数将 return -1
我认为这是一个错误。这是因为'\xFF'.charCodeAt(0) << 24 === 255 << 24
超出了补码的最大范围Math.pow(2, 32-1)-1
,因此溢出到-16777216
。此处给出的函数不会遇到该转换问题。
我正在编写一个共享代码库,我们有 'no bitwise operations' 的 linting 规则。但是,我正在使用一个简短的实用函数将二进制字符串转换为 unsigned int 32,big-endian。效果很好:
// converts a four-character string into a big endian 32-bit unsigned integer
stringAsUInt32BE(binString) {
return (binString.charCodeAt(0) << 24) + (binString.charCodeAt(1) << 16) +
(binString.charCodeAt(2) << 8) + binString.charCodeAt(3);
};
如果没有按位运算,我怎么能做到这一点?谢谢!
您可以使用具有 2 个不同视图的 ArrayBuffer。使用 Uint8Array
写入字节并使用 DataView
指定大端顺序读出一个值,如下所示:
stringAsUInt32BE(binString) {
var buffer = new ArrayBuffer(4);
var uint8View = new Uint8Array(buffer);
uint8View[0] = binString.charCodeAt(0);
uint8View[1] = binString.charCodeAt(1);
uint8View[2] = binString.charCodeAt(2);
uint8View[3] = binString.charCodeAt(3);
return new DataView(buffer).getUint32(0, false); // false for big endian
}
当不支持类型化数组时,使用位操作在旧版浏览器上效果更好。
您可以将 << x
替换为 * Math.pow(2, x)
。
这两个语句的主要区别在于非常大或负输入的行为 x
,例如按位运算符将其操作数转换为二补数,而其他算术运算符则不会。
// converts a four-character string into a big endian 32-bit unsigned integer
function stringAsUInt32BE(binString) {
return binString.charCodeAt(0) * 16777216 + binString.charCodeAt(1) * 65536 + binString.charCodeAt(2) * 256 + binString.charCodeAt(3);
}
console.log(stringAsUInt32BE('\xFF\xFF\xFF\xFF')); // 4294967295
console.log(stringAsUInt32BE('\x00\x00\x00\x00')); // 0
注意 stringAsUInt32BE('\xFF\xFF\xFF\xFF')
的行为:您的原始函数将 return -1
我认为这是一个错误。这是因为'\xFF'.charCodeAt(0) << 24 === 255 << 24
超出了补码的最大范围Math.pow(2, 32-1)-1
,因此溢出到-16777216
。此处给出的函数不会遇到该转换问题。