注意:我在C ++的Arduino变体中编写以下代码。
从给定的浮点数(总是带有四位小数),我希望只将小数部分(“尾数”)提取为整数。
所以我尝试了这种方法:
void ExtractDecimalPart(float Value) {
int IntegerPart = (int)(Value);
int DecimalPart = 10000 * (Value - IntegerPart); //10000 b/c my float values always have exactly 4 decimal places
Serial.println (DecimalPart);
}
但上述结果如下:
ExtractDecimalPart (1234.5677); //prints 5677
ExtractDecimalPart (1234.5678); //prints 5677
ExtractDecimalPart (1234.5679); //prints 5678
注意后两个打印错了;我猜这是由于浮点精度问题。
解决上述问题的经济方法是什么?
答案 0 :(得分:2)
这是一个很酷的问题。
我将假设ardiuno正在使用IEEE 754 当你设置一个等于1234.5677的浮点数时,最接近4个字节的浮点数是1.2345677490234375E3,它看起来像十六进制的0x449A522B。
但是当您将1234.5678放入浮点数时,它可以形成的最佳数字是1.2345677490234375E3 这只是短暂的。在十六进制中,它是0x449A522B。
因此,在简短的浮动中,只能存储需要使用数字的数字的数字。
答案 1 :(得分:1)
避免浮点精度问题的最简单方法是将数字转换为字符串,然后仅打印点之后的数字。
修改强>
我不确定如何使用arduino的版本c++
,所以请随时编辑我的答案以添加每个人的示例!
答案 2 :(得分:0)
32位float
有23位尾数,因此它只能保存约7位精度。您的示例使用8位数字,因此最后一个只是“垃圾”。您必须使用更高精度的浮点类型(标准C ++中为double
和long double
)。
在Arduino上取决于变体you may have a standard compliant 64-bit double
type or not。如果double
与float
完全相同,则您有多种解决方案:
double
数学库。
double
在8位MCU上的成本太高,那么您可以创建自定义浮点类型,如40位或48位。float-float
arithmetic类型like this。您可以在this question或fixed-point代码中找到有关定点的更多信息