解包数字导致顺序混乱。

huangapple go评论82阅读模式
英文:

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 &lt; 4; i++) {
      const num = (packed &gt;&gt; (i * 16)) &amp; 0xffff

      const signedNum = num &lt; 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),但更好的解决方案是使用BigUint64ArrayInt16Array作为对同一缓冲区的视图进行转换:

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 BigInts). But 0x0001000200030004 cannot be represented using 32 bits, so the code does not work properly. The solution is to simply use BigInts 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 &gt;= 0n; i--) {
      const num = (packed &gt;&gt; (i * 16n)) &amp; 0xffffn;
      const signedNum = num &lt; 0x8000n ? num : -(0x10000n - num);
      output.push(signedNum);
    }
  }
  return output;
}
console.log(unpack([0x0001000200030004n]).map(x =&gt; x.toString()));

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月10日 23:20:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76655161.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定