我想在微控制器上按比例因子计算多个值,我不能使用浮点值。例如,一旦我得到值 170,它乘以比例因子 ex。0.00065,所以结果是 0.1105,我只需要 0.11。我有从 -500 到 +500 的值。我知道这是关于固定点的事情,但我不知道如何解决它。谢谢帮助
2 回答
如果您的输入是一个整数,并且只有输出需要是定点,那么这相当简单。
让我们使用 16.16 固定点。这意味着您有 16 位小数和 16 位整数。要将整数转换为定点,只需左移 16 位(或乘以 65536)。
您的输入是170
, 或0xAA
。所以定点表示将是0xAA0000
。
您想乘以 0.00065,即0x002b
.
要相乘,您需要将数字相乘,然后取消其中一个比例(两个输入都被缩放,因此结果将被缩放两次),或者在相乘之前取消其中一个比例。
0xaa0000 * 0x2b = 0x1c8e0000
0x1c8e0000 >> 16 = 0x1c8e
但是请注意,这可能会因更大的输入而溢出。如果您尝试使用 500,它将产生大于 32 位的值。
如果你的输入是一个整数,你可以让它保持不变。让我们这样做:
0xaa * 0x2b = 0x1c8e
相同的答案,但没有变化。但是,您的输入显然只能是整数。
无论哪种方式,0x1c8e
都是您的答案,但以 65536 表示。如果您将该数字取十进制 (7310) 并除以 65536,您将得到 0.11154...,这是您想要的答案的近似值。
您可以使用固定点选择您喜欢的任何分数/整数拆分,甚至可以混合搭配。当您执行任何数学运算时,您只需要考虑拆分的位置,通常会适当地移动输入或输出。要处理的主要问题是为您要执行的操作选择一种不会溢出或下溢的格式。
要打印出这些值,您只需要一点整数操作。
让我们取值0xaa1c8e
。首先,通过移位 16 来取整数部分。得到 0xaa。
现在取分数,即 0x1c8e。乘以您想要的数字的适当数量。让我们乘以 100,得到两位小数。这给出了 0xb2778。将其移回 16,只剩下 0xb。
如果您使用字符串 printf: "%d.%02d", 0xaa, 0xb
,您将得到“170.11”,这是正确的。
这是一个粗略且现成的示例:
int a = (0.00065 * 65536 + 0.5); // Convert the float value to fixed point, with rounding.
int b = 170;
int m = b * a;
bool n = false;
if(m < 0) {m = -m; n=true;}
int i_part = m >> 16;
int f_part = m & 0xffff;
f_part *= 100;
f_part >>= 16;
printf("%s%d.%02d\n",n?"-":"",i_part,f_part);
用 2 个整数表示您的固定点,并在需要执行某些操作时同时使用它们。例如,0.11 = 11/100
, 所以你可以有两个整数变量, numerator( 11
) 和 denominator( 100
) ,它们一起代表一个与你的值相对应的有理数。