在javascript中将字节数组解码为最多64位的有符号整数 [英] Decode a byte array to a signed integer up to 64 bit in javascript

查看:110
本文介绍了在javascript中将字节数组解码为最多64位的有符号整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道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.

推荐答案

当将字节数据打包成更宽的整数时,所有字节必须被视为无符号,所有操作必须无符号执行。



需要使用按位运算:

When packing byte data into a wider integer, all bytes must be treated as unsigned and all operations must be performed unsigned.

This requires using bitwise operations:
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字节)。





因为你需要整数运算而没有舍入错误,你不能指望最终值的正确结果大于 Number.MAX_SAFE_INTEGER - JavaScript | MDN [ ^ ]限制为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]


此页解释了一个简单易用的解决方案:



•将右端的所有位加起来,直到第二个最高位。

•最高位不会被添加为2 ^ i而是添加为-2 ^ i。



我的代码工作在一个更大的范围内,有一个数组和一个pos来读取。



This page explains a good and simple solution:

• Add up all bits from the right end, up to the second most significant bit.
• The most significant bit is not added as 2^i but as -2^i.

My code works in a larger scope that has an array and a pos to read from.

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位的有符号整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆