Go例程创建一个字节数组,其中包含8字节Big Endian的Uint64号5577006791947779410 [77,101,130,33,7,252,253,82].
在JavaScript代码中,我将这些字节作为Uint8Array接收.我们知道JavaScript当前不支持Uint64作为安全数字类型,并且不能对大于32位的整数执行按位运算,因此像buf [0]<< 56永远不会奏效. 那么将这些字节直接解码为数字字符串“5577006791947779410”的过程是什么? 附:我知道在JavaScript中使用大整数有plenty of libraries,但一般来说它们很大并提供了大量的数学运算,这里我不需要.我正在寻找一个简单的现代直接解决方案,只需将BE打包的Uint64和Int64字节解码为数字字符串.你有什么想法吗?
解决方法
我从https://stackoverflow.com/a/21668344/3872370开始修改它:
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,82],signed: false,expectation: '5577006791947779410' },{ inp: [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}`); });
首先,通过检查最高位是否被设置(字节[0]> 128)来计算符号.对于负数,必须取消位(255字节),并且必须将1添加到数字中(因此最后一个字节为256而不是255).
forEach循环的基本思想是将每个字节分成十进制数字(字节%10并计算下一个数字的开销(字节 – 数字[i])/ 10和Math.floor(字节/ 10)).对于下一个字节,必须添加最后字节数字的移位结果(byte = digits [i] * 256 resp.digital [i]<< 8). 该代码针对简洁性,简单性和灵活性进行了优化.如果您正在使用字符串而不是字节或数字,并且不想使用任何库,那么转换性能似乎并不重要.否则该函数可以针对性能进行优化:可以同时处理多达四个字节,另外一个只需要替换0x100和0x80(在(U)Int64的情况下只剩下两个字节组)forEach循环可以展开.对十进制数字进行分组可能不会提高性能,因为生成的字符串必须用零填充,因此需要在最终结果中删除前导零.