英文:
Unpacking number is resulting in out of order
问题
我有以下变量:
const input = [0x0001000200030004]
而且我有一个从中解包四个数字的函数(它来自一个C++代码,其中有四个int16_t打包到一个uint64_t中):
export function unpack(input: number[]) {
const output: number[] = []
for (const packed of input) {
for (let i = 0; i < 4; i++) {
const num = (packed >> (i * 16)) & 0xffff
const signedNum = num < 0x8000 ? num : -(0x10000 - num)
output.push(signedNum)
}
}
return output
}
这个函数基本上是工作的;但是,它的顺序不对。
输出不是[1, 2, 3, 4],而是[1, 2, 4, 3]。
我做错了什么?
英文:
I have the following variable:
const input = [0x0001000200030004]
And I have a function to unpack four numbers from 1 (it cames from a C++ code, where I have four int16_t that are packed into a single uint64_t)
export function unpack(input: number[]) {
const output: number[] = []
for (const packed of input) {
for (let i = 0; i < 4; i++) {
const num = (packed >> (i * 16)) & 0xffff
const signedNum = num < 0x8000 ? num : -(0x10000 - num)
output.push(signedNum)
}
}
return output
}
The function kind works; however, it is out of order.
Instead of the output being [1, 2, 3, 4], it is [1, 2, 4, 3].
What I'm doing wrong?
答案1
得分: 3
问题已经在评论和@Unmitigated的回答中被识别出来(即位运算符在JS中使用32位数字,无法表示您的uint64),但更好的解决方案是使用BigUint64Array
和Int16Array
作为对同一缓冲区的视图进行转换:
function unpack(input) {
const buffer = new BigUint64Array(input).buffer;
return Array.from(new Int16Array(buffer));
}
console.log(unpack([0x0001000200030004n]))
然而,您可能需要一个DataView
来控制字节顺序,这可能与执行C++代码的平台的字节顺序不同。
英文:
The issue has already been identified in the comments and in @Unmitigated's answer (namely that bitwise operators work on 32 bit numbers in JS, which cannot represent your uint64), but a better solution is to use a BigUint64Array
and a Int16Array
as views on the same buffer for the conversion:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function unpack(input) {
const buffer = new BigUint64Array(input).buffer;
return Array.from(new Int16Array(buffer));
}
console.log(unpack([0x0001000200030004n]))
<!-- end snippet -->
However, you might need a DataView
to control endianness, which might be different than the one of the platform where your C++ code is executed.
答案2
得分: 2
问题在于位运算符首先将其操作数转换为32位整数(除非使用BigInt
)。但0x0001000200030004
不能用32位表示,所以代码无法正常工作。解决方案是简单地使用BigInt
来执行所有操作。
您还需要颠倒迭代的顺序或在最后颠倒输出,以获取最高位数字。
function unpack(input) {
const output = [];
for (const packed of input) {
for (let i = 3n; i >= 0n; i--) {
const num = (packed >> (i * 16n)) & 0xffffn;
const signedNum = num < 0x8000n ? num : -(0x10000n - num);
output.push(signedNum);
}
}
return output;
}
console.log(unpack([0x0001000200030004n]).map(x => x.toString()));
这段代码将解决您的问题。
英文:
The issue is that bitwise operators convert their operands to 32-bit integers first (unless working with BigInt
s). But 0x0001000200030004
cannot be represented using 32 bits, so the code does not work properly. The solution is to simply use BigInt
s for all operations instead.
You would also need to reverse the order of iteration or reverse the output at the end to get the most significant digits first.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function unpack(input) {
const output = [];
for (const packed of input) {
for (let i = 3n; i >= 0n; i--) {
const num = (packed >> (i * 16n)) & 0xffffn;
const signedNum = num < 0x8000n ? num : -(0x10000n - num);
output.push(signedNum);
}
}
return output;
}
console.log(unpack([0x0001000200030004n]).map(x => x.toString()));
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论