【问题标题】:32-bit fractional multiplication with cross-multiplication method (no 64-bit intermediate result)带叉乘法的 32 位小数乘法(无 64 位中间结果)
【发布时间】:2013-02-05 17:47:31
【问题描述】:

我正在 16 位处理器上编写定点语音增强算法。在某些时候,我需要进行 32 位小数乘法。我已经阅读了其他有关逐字节进行 32 位乘法的帖子,我明白了为什么这适用于 Q0.31 格式。但我使用不同的 Q 格式,小数位数不同。

所以我发现对于小于 16 的小数位,这是有效的:

(low*low >> N) + low*high + high*low + (high*high << N)

其中 N 是小数位数。我读过low*low 结果应该是无符号的,低字节本身也应该是无符号的。一般来说,这可以在任何小于 16 位的 Q 格式中给出我想要的结果。

现在,当小数位超过 16 时,它会变得很棘手。我尝试了几种移位,low*lowhigh*high 的不同移位我试图把它写在纸上,但我想不通出来吧。

我知道这可能非常简单,但整个想法让我难以理解,我将不胜感激一些 cmets 或指南!

【问题讨论】:

    标签: multiplication fixed-point


    【解决方案1】:

    这是相同的公式。对于 N > 16,移位仅意味着您丢弃了一个完整的 16 位字,该字会溢出或下溢。 low*low >> N 表示仅将 32 位乘法结果的高位字中的 N-16 位移位并添加到结果的低位字中。 high * high

    【讨论】:

      【解决方案2】:

      有一些想法在起作用。

      首先,将 2 个较短的整数相乘以产生较长的乘积。考虑 2 个 32 位整数的无符号乘法,通过它们的 16 位“一半”相乘,每个乘积产生一个 32 位乘积,总乘积为 64 位:

        a * b = (a_hi * 216 + a_lo) * (b_hi * 216 + b_lo) =

        a_hi * b_hi * 232 + (a_hi * b_lo + a_lo * b_hi) * 216 + a_lo * b_lo。

      现在,如果你需要一个有符号乘法,你可以从无符号乘法中构造它(例如从上面)。

      假设a = 0,a *signed b 必须相等

        264 - ((-a) *unsigned b),其中

        -a = 232 - a(因为这是 2 的补码)

      IOW,

        a *签名 b =

        264 - ((232 - a) *unsigned b) =

        264 + (a *unsigned b) - (b * 232),其中 264 可以丢弃,因为我们只使用 64 位。

      以完全相同的方式,您可以计算 a >= 0 和 b signed b 并且必须得到对称结果:

        (a *unsigned b) - (a * 232)

      您可以类似地证明,对于 a

        (a *unsigned b) - ((a + b) * 232)

      因此,首先将 a 和 b 相乘为无符号,然后如果 a


      现在我们可以将 32 位有符号整数相乘并得到 64 位有符号乘积,我们终于可以转向小数部分了。

      现在假设在 a 和 b 的这 32 位中,N 位用于小数部分。这意味着如果您将 a 和 b 视为普通整数,它们将比它们实际表示的值大 2N 倍,例如1.0 看起来像 2N(或 1

      因此,如果将两个这样的整数相乘,则乘积将是 2N*2N = 22*N 倍比它应该代表的,例如1.0 * 1.0 看起来像 22*N (或 1 N (或将其在算术上向右移动 N 个位置)。很简单。


      谨言慎行,以防万一……

      在 C(和 C++)中,您不能合法地将变量向左或向右移动与变量中包含的相同或更多位数。代码会编译,但不会像您期望的那样工作。所以,如果你想移动一个 32 位变量,你可以将它向左或向右移动 0 到 31 个位置(31 是最大值,而不是 32)。

      如果将有符号整数左移,则不能合法地溢出结果。所有带符号的溢出都会导致未定义的行为。所以,你可能想坚持使用 unsigned。

      负符号整数的右移是特定于实现的。它们可以进行算术移位或逻辑移位。哪一个,这取决于编译器。因此,如果您需要两者之一,则需要确保您的编译器直接支持它 或以其他方式实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多