问题描述
我知道JavaScript无法准确表示所有64位整数。但它可以精确地表示大于32位的数字。这就是我的需要。无论JavaScript能给我什么精确度。
我有一个已知长度的字节数组。它有1,2,4,8或16个字节。它可以包含有符号或无符号整数,我知道它是什么。数据是big-endian(网络字节顺序)。
如何从该字节数组中获取数值?
有一些使用乘法和加法的简单解决方案,在负数上完全失败。有超过32位的DataView没有任何帮助。我对一个好的,简单的,优选的高效的纯JavaScript解决方案感兴趣。不幸的是,我想不出这样一种处理负二补值的方法。
我尝试过的方法:
我尝试过正值:
I know that JavaScript can't precisely represent all 64 bit integer numbers. But it can precisely represent numbers larger than 32 bit. And that's what I need. With whatever precision JavaScript can give me.
I have a byte array of known length. It has 1, 2, 4, 8 or 16 bytes. And it can contain a signed or unsigned integer, I know which it is. The data is big-endian (network byte order).
How can I get the number value from that byte array?
There are simple solutions with multiply and add that completely fail on negative numbers. There's DataView that isn't of any help with more than 32 bits. I'm interested in a nice and simple and preferable efficient pure JavaScript solution to handle this. And unfortunately I can't think of such a way to handle negative two-complement values.
What I have tried:
I have tried it for positive values:
function readInt(array) {
var value = 0;
for (var i = 0; i < array.length; i++) {
value = (value * 256) + array[i];
}
return value;
}
但它显然在负数上失败,而是给我无符号值。
But it obviously fails on negative numbers, instead giving me unsigned values.
推荐答案
for (var i = 0; i < array.length; i++) {
value = (value << 8) | array[i];
}
但这仅限于32位值,因为JavaScript会通过按位运算忽略更高位。
一种可能的解决方案(我没有测试过它会使值无符号:
But this is limited to 32-bit values because JavaScript ignores higher bits with bitwise operations.
A possible solution (I have not tested it) would be making the values unsigned:
for (var i = 0; i < array.length; i++) {
value *= 256;
if (array[i] < 0) {
value += 256 + array[i];
} else {
value += array[i];
}
}
这里的技巧是数组值是-128到+127范围内的字节。如果字节值为负,则添加256以使其成为相应的无符号值。
当使用整数执行操作时,它应该最多可以工作63位。如果JavaScript解释器决定在内部执行浮点运算,结果将变得不精确,超过53位。
所以没有解决方案(据我所知) )128位(16字节)。
因为你需要整数运算而没有舍入错误,你不能指望最终值的正确结果大于 []限制为53位(双精度浮点值的尾数位数)。
[/ EDIT]
The trick here is that the array values are bytes in the range -128 to +127. If a byte value is negative, 256 is added to make it the corresponding unsigned value.
It should work for up to 63 bits when the operations are performed using integers. If the JavaScript interpreter decides to perform floating point operations internally, the result will become inexact with more than 53 bits.
So there is no solution (as far as I know) for 128 bits (16 bytes).
Because you need integer operations without rounding errors here, you can not expect proper results for final values greater than Number.MAX_SAFE_INTEGER - JavaScript | MDN[^] which is limited to 53 bits (the number of mantissa bits for double precision floating point values).
[/EDIT]
function readInt(size) {
var value = 0;
var first = true;
while (size--) {
if (first) {
let byte = array[pos++];
value += byte & 0x7f;
if (byte & 0x80) {
value -= 0x80;
// Treat most-significant bit as -2^i instead of 2^i
}
first = false;
}
else {
value *= 256;
value += array[pos++];
}
}
return value;
}
原始字节在数组
中提供(a Uint8Array
)和 pos
是下一个要读取的索引。此函数开始读取当前 pos
并前进 pos
,因为它读取之一size
bytes。
The raw bytes are provided in array
(a Uint8Array
) and pos
is the next index to read. This function starts to read at the current pos
and advances pos
as it reads one of the size
bytes.
这篇关于在javascript中将字节数组解码为最多64位的有符号整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!