32 位定点运算 1x1 不等于 1

32-bit fixed point arithmetic 1x1 does not equal 1

我正在实现 32 位有符号整数定点运算。 scale是从1到-1,INT32_MAX对应1,不知道是让INT32_MIN还是-INT32_MAX对应-1,暂且搁置。

我做了一些乘法和舍入操作,如下:

#define mul(a, b) ((int64_t)(a) * (b))
#define round(x) (int32_t)((x + (1 << 30)) >> 31)

然后可以使用 round(mul(a, b)).

求出两个数的乘积

检查身份时出现问题。 主要问题是 1x1 不是 1。它是 INT32_MAX-1。这显然不是我想要的,因为我想要位精度。我想这会影响附近的其他数字,因此如果操作数都是 INT32_MAX,则修复不是仅加 1 的情况。 此外,-1x-1 不是 -1,1x-1 不是 -1,并且 -1x-1=-1。所以 none 的身份成立。

是否有简单的解决方法,或者这只是使用定点运算的症状?

在其一般形式中,定点格式将数字 x 表示为整数 xs 。通常,s是某个基b的幂,s = bp。例如,我们可能将一些美元 x 存储为 x•100,那么 $3.45 可能存储为 345。这里我们很容易看出原因这被称为“定点”格式:存储的数字在概念上将小数点插入固定位置,在这种情况下,最右边数字左边两位:“345”在概念上是“3.45”。 (这也可以称为小数点而不是小数点,允许基数 b 不是十的情况。并且 p 指定在哪里小数点被插入,p base-b 数字从右边开始。)

如果你让INT_MAX代表1,那么你就是在隐含地说s = INT_MAX。 (并且,由于 INT_MAX 不是任何其他整数的幂,我们有 b = INT_MAXp = 1.) 则−1 必须表示为−1•INT_MAX = -INT_MAX。它不会由 INT_MIN 表示(除了在古老的 C 实现中 INT_MIN = -INT_MAX)。

给定 s = INT_MAX,移位 31 位不是实现乘法的正确方法。给定两个数字 xy,表示为 abxy 的表示是通过将表示 ab 相乘并除以 s:

  • a表示x,所以a=xs.
  • b表示y,所以b=ys.
  • 然后ab/s = xsys/s = xys,而xys代表xy.

移位 31 除以 231,因此这与除以 INT_MAX 不同。此外,除法在硬件上通常很慢。您最好选择 s = 230 而不是 INT_MAX。然后你可以移动 30 位。

在计算ab/s的时候,我们经常会想要四舍五入。在除法之前将 ½s 添加到产品中是一种舍入方法,但它可能不是您想要的负产品。如果乘积为负,您可能需要考虑添加 −½s