我目前正在尝试弄清楚如何在定点表示中将两个数字相乘。
说我的数字表示如下:
[SIGN][2^0].[2^-1][2^-2]..[2^-14]
就我而言,数字10.01000000000000 = -0.25
.
例如,我将如何做0.25x0.25
或-0.25x0.25
等等?
希望你能帮忙!
我目前正在尝试弄清楚如何在定点表示中将两个数字相乘。
说我的数字表示如下:
[SIGN][2^0].[2^-1][2^-2]..[2^-14]
就我而言,数字10.01000000000000 = -0.25
.
例如,我将如何做0.25x0.25
或-0.25x0.25
等等?
希望你能帮忙!
乘以一个更大的变量,然后右移定点精度的位数。
您应该使用 2 的补码表示而不是单独的符号位。对此进行数学运算要容易得多,不需要特殊处理。范围也得到了改进,因为负 0 没有浪费的位模式。要乘法,只需像正常的定点乘法一样。正常的 Q2.14 格式将为 x的位模式存储值 x/2 14 ,因此如果我们有 A 和 B,那么
因此,您只需将 A 和 B 直接相乘,然后将乘积除以 2 14即可将结果返回为 x/2 14的形式,如下所示
AxB = ((int32_t)A*B) >> 14;
需要一个舍入步骤来获得最接近的值。您可以在Q 数字格式#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,这会使计算更加复杂,因为您需要拆分符号位,然后在最后将其组合回来。
这是 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 << 8
而不是1 << 16
。