5

我正在尝试用定点数解决乘法问题。数字是 32 位的。我的架构是 8 位的。所以这里是:

  1. 我使用 8.8 表示法,即 8 表示整数,8 表示分数。

  2. 我有 A78,它是 10.468。我取它的二进制补码,答案是 FFFFF588,我将它截断为 16 位作为 F588 并存储它。原因是,我只想将两个 2 字节数相乘。

  3. 现在,当我将此 F588(负 10.42 或 0x0A78)乘以 0xFF4B(即 0x00B5(0.707)的二进制补码)时,答案应该是 0x0766。或者类似的东西。

另一方面,我得到的是 66D8。

现在有趣的是:如果我将 B5 的负数存储在 32 位的二进制补码中,我得到 0xFF5266D8,我将其右移 8 位,然后截断为 16 位,答案是 0x5266。

另一方面,如果我将负数 10.42 存储在 32 位中,我得到 0xF58F66D8,在移位 8 位并截断后变为 8F66。

但是,如果我将两个数字都存储为 32 位格式,那么只有在移位和截断后才能得到正确的结果,即 0x0766。

为什么会这样?我知道当我们从 32 位到 16 位时,信息丢失是固有的,但是 0x07 与 0x55 有很大不同。我将非常感谢您的回复。

4

1 回答 1

4

让我们只看整数表示。您有两个 16 位整数xy,并形成它们的 16 位二进制补码。但是,您将这些 16 位补码保存在 32 位对象中。在 32 位中,您拥有的是 65536–<em>x 和 65536–<em>y。(例如,您从 0xa78 开始,将其补充为 0xfffff588,并丢弃位以获得 0xf588。这等于 0x10000-0xa78。)

当您将这些相乘时,结果为 65536•65536 – 65536•<em>x – 65536•<em>y + x •<i>y。

65536•65536 是 2 32,因此它消失了,因为无符号 32 位算术是以 2 32为模执行的。剩下 – 65536•<em>x – 65536•<em>y + x •<i>y。

现在你可以看到问题了:x •<i>y 是两个 16 位值的乘积,所以它流入了 32 位的高 16 位。在那里,你仍然有 - 65536•<em>x - 65536•<em>y,这是你不想要的。

一个简单的方法是乘以保留所有 32 位的补码。例如,当你取 0xa78 的二进制补码时,你得到 0xfffff588。然后你丢弃了高位,只保留 0xf588。如果你不这样做,你会将 0xfffff588 乘以 0xffffff4b,乘积将是 0x766d8,当为分数移动时,将是 0x766,这就是你想要的结果。

如果由于将二进制补码存储到 16 位对象中而丢失了高位,则只需在重新加载对象时通过扩展符号位来恢复它们。也就是说,取第 15 位并在第 16 位到第 31 位重复。一个简单的方法是将 16 位对象加载到 16 位有符号整数,然后将 16 位有符号整数转换为无符号 32-位整数。

于 2013-01-23T21:02:59.683 回答