Vis*_*ioN 8 javascript string int64 uint64 ecmascript-6
让我们考虑以下情况.
Go例程创建一个字节数组,其中包含8字节Big Endian 的Uint64编号.5577006791947779410
[77, 101, 130, 33, 7, 252, 253, 82]
在JavaScript代码中,我收到这些字节为Uint8Array
.我们知道JavaScript当前不支持Uint64作为安全数字类型,并且不能对大于32位的整数执行按位运算,所以类似的东西buf[0] << 56
永远不会起作用.
那么将这些字节直接解码为数字字符串的过程是什么"5577006791947779410"
?
PS我知道在JavaScript中有很多 用于处理大整数的 库,但通常它们很大并且提供了大量的数学运算,这里我不需要.我正在寻找一个简单的现代直接解决方案,只需将BE打包的Uint64和Int64字节解码为数字字符串.你有什么想法吗?
编辑:对于转换(U)int64我现在肯定会推荐@ LS_DEV的解决方案.我只有在拥有未知或更大的字节数时才使用我的解决方案.
我从/sf/answers/1516784111/开始并修改它:
function Int64ToString(bytes, isSigned) {
const isNegative = isSigned && bytes.length > 0 && bytes[0] >= 0x80;
const digits = [];
bytes.forEach((byte, j) => {
if(isNegative)
byte = 0x100 - (j == bytes.length - 1 ? 0 : 1) - byte;
for(let i = 0; byte > 0 || i < digits.length; i++) {
byte += (digits[i] || 0) * 0x100;
digits[i] = byte % 10;
byte = (byte - digits[i]) / 10;
}
});
return (isNegative ? '-' : '') + digits.reverse().join('');
}
const tests = [
{
inp: [77, 101, 130, 33, 7, 252, 253, 82],
signed: false,
expectation: '5577006791947779410'
},
{
inp: [255, 255, 255, 255, 255, 255, 255, 255],
signed: true,
expectation: '-1'
},
];
tests.forEach(test => {
const result = Int64ToString(test.inp, test.signed);
console.log(`${result} ${result !== test.expectation ? '!' : ''}=== ${test.expectation}`);
});
Run Code Online (Sandbox Code Playgroud)
首先,通过检查最顶部位是否设置(bytes[0] > 128
)来计算符号.对于负数,必须将位取消(255 - byte
),并且必须将1添加到数字(因此256
而不是255
最后一个字节).
foreach循环的基本思想是每个字节分成其十进制数字(byte % 10
和计算开销(byte - digits[i]) / 10
RESP.Math.floor(byte / 10)
为下一个数位).对于下一个字节,必须添加最后字节数字(byte += digits[i] * 256
resp.digits[i] << 8
)的移位结果.
该代码针对简洁性,简单性和灵活性进行了优化.如果您正在处理字符串而不是字节或数字,并且不想使用任何库,那么转换性能似乎并不重要.否则,该函数可以针对性能进行优化:最多可以同时处理四个字节,一个只需要替换0x100
和0x80
,另外(在(U)Int64的情况下只剩下两个字节组)forEach
可以展开循环.对十进制数字进行分组可能不会提高性能,因为生成的字符串必须用零填充,因此需要在最终结果中删除前导零.
归档时间: |
|
查看次数: |
1649 次 |
最近记录: |