【问题标题】:How do you multiply two fixed point numbers?如何将两个定点数相乘?
【发布时间】:2012-12-23 03:16:54
【问题描述】:

我目前正试图弄清楚如何将两个数字相乘以定点表示。

说我的数字表示如下:

[SIGN][2^0].[2^-1][2^-2]..[2^-14]

就我而言,号码10.01000000000000 = -0.25

例如0.25x0.25-0.25x0.25 等我该怎么做?

希望你能帮忙!

【问题讨论】:

  • 在一张纸上还是您使用某种形式的编程语言?如果是这样,您应该将其添加到标签中。
  • 一个计算器似乎很合适......
  • 哈哈,我对这个网站还很陌生,所以我不知道如何接受发布的问题!?
  • 您单击您最喜欢的答案旁边的向上/向下按钮旁边的复选框轮廓。它会变成绿色,如果你没有自己写答案,你会得到 2 分。
  • 使用无符号整数类型数组而不是单独的位表示并使用内置算术,看看这里stackoverflow.com/q/18465326/2521214 或搜索 bigint 乘法。它的方式比位方法快得多

标签: multiplication fixed-point


【解决方案1】:

乘以一个更大的变量,然后右移定点精度的位数。

【讨论】:

  • 您甚至没有指定编程语言,所以我不知道该举什么样的例子。
【解决方案2】:

您应该使用 2 的补码表示,而不是 seperate sign bit。对此进行数学运算要容易得多,不需要特殊处理。范围也得到了改进,因为负 0 没有浪费的位模式。要乘法,只需像正常的定点乘法一样。正常的 Q2.14 格式将为 x 的位模式存储值 x/214,因此如果我们有 A 和 B 那么

所以您只需将 A 和 B 直接相乘,然后将乘积除以 214 即可将结果返回为 x/214 的形式 p>

AxB = ((int32_t)A*B) >> 14;

需要一个舍入步骤来获得最接近的值。您可以在Q number format#Math operations 中找到方法。最简单的四舍五入方法就是像这样将最后移出的位(即第一个小数位)加回

AxB = (int32_t)A*B;
AxB = (AxB >> 14) + ((AxB >> 13) & 1);

您可能还想阅读这些

使用 2 位可以表示 [-2, 1] 的整数范围。所以使用 Q2.14 格式,-0.25 将被存储为11.11000000000000。使用 1 个符号位只能表示 -1、0、1,这会使计算更加复杂,因为您需要拆分符号位,然后在最后将其组合回来。

【讨论】:

  • 好吧,但是如果你有足够大的位数(所以你没有足够大的整数类型变量可供你使用,并且需要自己编写算术),那么单独的符号是更好的选择。跨度>
  • @Spektre:使用单独的符号只会增加复杂性。加法,减法,乘法和除法都需要程序员注意符号。而 2 的补码对于有符号和无符号数字只需要一个严格的版本
  • 尝试在数字 (128*32) 位宽上执行此操作,然后您将开始看到好处。如果您使用已经存在的数据类型算术,那么您是正确的。顺便提一句。 bignum +,- 操作中的几个 if 并不像 *,/,%,log,pow 对 2 的补码那样可怕
【解决方案3】:

这是一个 C 语言的简单示例:

int a =  0.25 * (1 << 16);
int b = -0.25 * (1 << 16);
int c = (a * b) >> 16;
printf("%.2f * %.2f = %.2f\n", a / 65536.0, b / 65536.0 , c / 65536.0);

您基本上将所有内容都乘以一个常数,使小数部分进入整数范围,然后将这两个因子相乘,然后(可选)除以其中一个常数,将乘积返回到标准范围,以供将来计算使用.这就像以小数美元表示的价格乘以 100,然后以美分计算(即 1.95 美元 * 100 美分/美元 = 195 美分)。

注意不要超出要乘入的变量的范围。您的常量可能需要更小以避免溢出,例如在上面的示例中使用1 &lt;&lt; 8 而不是1 &lt;&lt; 16

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多