无符号数的不动点乘法

use*_*318 5 c numbers fixed-point

我试图解决定点数的乘法问题.数字是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有很大的不同.我将非常感谢您的回复.

Eri*_*hil 4

让\xe2\x80\x99s 只看整数表示。您有两个 16 位整数xy,并且形成它们的 16 位补码。但是,您将这些 16 位补码保留在 32 位对象中。在 32 位中,您拥有的是 65536\xe2\x80\x93 x和 65536\xe2\x80\x93 y。(例如,您从 0xa78 开始,对其进行补足以生成 0xfffff588,然后丢弃一些位以获得 0xf588。这等于 0x10000-0xa78。)

\n\n

当您将它们相乘时,结果为 65536\xe2\x80\xa265536 \xe2\x80\x93 65536\xe2\x80\xa2 x \xe2\x80\x93 65536\xe2\x80\xa2 y + x \xe2\x80\ xa2 y

\n\n

65536\xe2\x80\xa265536 是 2 32,因此它消失,因为无符号 32 位算术是以 2 32为模执行的。剩下 \xe2\x80\x93 65536\xe2\x80\xa2 x \xe2\x80\x93 65536\xe2\x80\xa2 y + x \xe2\x80\xa2 y

\n\n

现在你可以看到问题了:x \xe2\x80\xa2 y是两个 16 位值的乘积,因此它流入 32 位的高 16 位。在那里,您仍然有 \xe2\x80\x93 65536\xe2\x80\xa2 x \xe2\x80\x93 65536\xe2\x80\xa2 y,这是您不想要的。

\n\n

实现此目的的一个简单方法是通过乘法来保留所有 32 位的补码。例如,当你取 0xa78 的两个\xe2\x80\x99s 补码时,你得到 0xfffff588。然后你丢弃高位,只保留 0xf588。如果不这样做,则将 0xfffff588 乘以 0xffffff4b,结果将是 0x766d8,当转换为分数时,将是 0x766,这就是您想要的结果。

\n\n

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

\n