【问题标题】:Fixed point multiply/divide for 15.16 numbers15.16 数字的定点乘法/除法
【发布时间】:2011-01-22 18:22:57
【问题描述】:

我正在寻找一种算法来乘除定点 15.16 数字。

我已经有加减法了。这些很简单——简单的 32 位加减法。通过乘除法,我还可以添加许多三角函数和指数/对数函数。而且我想我可以只处理乘法,因为我的库有一个倒数函数,我可以用它来实现除法:a * (1/b) = a / b。但是 32 位乘法不起作用,因为它忽略了小数点。

我正在开发一个 16 位微控制器,因此我想避免超过 32 位乘法,这在我的处理器上大约需要 4 个周期。不过这并不重要,我只是想替换浮点数学。

我听说我需要移动或旋转结果,但我不确定这将如何帮助或具体如何移动它。任何建议或帮助表示赞赏!

【问题讨论】:

    标签: fixed-point


    【解决方案1】:

    想想是这样的:你的数字 a.b 表示为 (a.b * 65536)

    如果你将 a.b * c.d 相乘,你得到的值是 (a.b * 65536) * (c.d * 65536),所以要将它放回正确的表示中,你需要除以 65536。

    当您将 a.b / c.d 相除时,您得到的值为 (a.b * 65536) / (c.d * 65536),因此要将其放回正确的表示中,您需要乘以 65536。您应该在除法之前乘以 65536在结果中保留尽可能多的位。

    当然,如果您的处理器速度更快,您可以用 (> 16) 替换为 (/ 65536)。

    这里是 a.b * c.d:

    uint32_t result_low = (b * d);
    uint32_t result_mid = (a * d) + (b * c);
    uint32_t result_high = (a * c); 
    uint32_t result = (result_high << 16) + result_mid + (result_low >> 16)
    

    【讨论】:

    • 当然可以。我的解释是算法,而不是实现。
    • Microchip 还为 PIC24 和 dsPIC 提供了定点数学库;见microchip.com/stellent/…
    【解决方案2】:

    首先理论:假设有符号数,将 Q15.16 乘以另一个 Q15.16 将得到 Q(15+15+1).(16+16) = Q31.32 数。因此,您需要一个 64 位整数变量来保存结果。

    如果您的编译器有 64 位整数类型,只需使用它并让编译器弄清楚如何在 16 位 CPU 上执行 32 位 x 32 位乘法(这就是编译器的用途):

    int32_t a_15q16, b_15q16;
    int64_t res_31q32 = (int64_t)a_15q16 * (int64_t)b_15q16;
    

    您之后对 Q31.32 结果的处理取决于您的应用程序。

    您可能想知道为什么结果需要 31 整数而不是 30。事实上,仅当您将 -2^15 乘以 -2^15 的情况下才需要额外的位。如果保证您的操作数永远不会同时等于 -2^15,则可以假设 Q30.32 结果。

    要了解您的编译器是否支持 64 位整数,您可能需要查看编译器手册。如果这是 C99 编译器,请查看 stdint.h 标头中是否有 int64_t 类型。

    【讨论】:

      【解决方案3】:

      使用 64 位乘法可以轻松完成乘法运算:(a * b) &gt;&gt; 16。同样,除法也很容易用 64 位完成:(a &lt;&lt; 16) / b。根据您的舍入/错误要求,您可能希望稍微复杂化,以使输出的最后一位正确。

      【讨论】:

      • @Paul R,我认为我的处理器上的 32x32 大约需要 4 个周期,这不是一个大问题。
      • @Paul R,我确实提前说明了这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2011-05-06
      • 1970-01-01
      相关资源
      最近更新 更多