c - 已知范围内的定点乘法

标签 c math fixed-point

我正在尝试乘以 A*B在 16 位定点中,同时保持尽可能高的准确性。 A是 16 位无符号整数范围,B除以 1000 并且总是在 0.001 之间和 9.999 .我已经有一段时间没有处理这样的问题了,所以:

  • 我知道我可以做 A*B/1000移动到 32 位变量后,然后剥离回 16 位
  • 我想让它比那个更快
  • 我想在不移动到 32 位的情况下完成所有操作(因为我只有 16 位乘法)

  • 有没有什么简单的方法可以做到这一点?

    编辑:A将在 0 到 4000 之间,因此所有可能的结果也在 16 位范围内。

    编辑:B来自用户,在 X.XXX 中逐位设置掩码,这就是为什么操作是 /1000 .

    最佳答案

    不,你必须去32位。通常,两个 16 位数字的乘积将始终为您提供 32 位宽的结果。

    您应该检查您正在处理的 CPU 的 CPU 指令集,因为 16 位机器上的大多数乘法指令都可以选择将结果直接作为 32 位整数返回。

    这会对你有很大帮助,因为:

    short testfunction (short a, short b)
    {
      int A32 = a;
      int B32 = b;
    
      return A32*B32/1000
    }
    

    会强制编译器进行 32 位 * 32 位乘法。在您的机器上,这可能会非常慢,甚至仅使用 16 位乘法就可以分多个步骤完成。

    一点内联汇编甚至更好的编译器内在函数都可以大大加快速度。

    以下是具有此类内在函数的 Texas Instruments C64x+ DSP 的示例:
    short test (short a, short b) 
    {
      int product = _mpy (a,b); // calculates product, returns 32 bit integer
      return product / 1000;
    }
    

    另一个想法:你要除以 1000。你的选择是不变的吗?使用 2 的幂作为定点数的基数会快得多。 1024 接近。你为什么不:
      return (a*b)/1024 
    

    反而?编译器可以通过使用右移 10 位来优化它。这应该比做倒数乘法技巧要快得多。

    关于c - 已知范围内的定点乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3276864/

    相关文章:

    c - C 中不带 float 的定点数

    c - 在 C 中实现定点数的麻烦

    c - 从 C 中正在运行的进程的 stdout fd 读取

    使用 C 指针和结构的链表程序中的冲突类型错误消息

    java - Java 中的等概率

    algorithm - 用大数求大数的模

    linux - 将用户值传递给 AWK 中的变量。我错过了什么?

    vhdl - 在vivado中显示定点值

    c - MPI 调试,段错误?

    c - 使用 libxml2 在现有 XML 中附加数据