精确地提取浮点数的小数部分
Extracting decimal part of a float accurately
注意:我在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
注意后两个打印出来错误;我猜这是由于浮点精度问题。
解决上述问题的经济方法是什么?
这是个很酷的问题。
我将假设arduino使用IEEE 754当你设置一个等于1234.5677的浮点数时,最接近4字节的数字是1.2345677490234375E3,在十六进制中看起来像0x449A522B。
但是当你把1234.5678放入浮点数时,它能形成的最佳数字是1.2345677490234375E3很短。十六进制格式为0x449A522B。
所以在短浮动只是不能存储数字,需要你使用的数字的数量
避免浮点精度问题的最简单方法是将数字强制转换为字符串,然后只打印点之后的内容。
编辑
我不知道如何用arduino的c++
版本做到这一点,所以请随意编辑我的答案来添加一个例子!
32位float
有23位尾数,所以它只能保持大约7位的精度。你的例子使用了8个数字,所以最后一个数字就是"垃圾"。必须使用更高精度的浮点类型(标准c++中的double
和long double
)。
在Arduino上,取决于变体,您可能有一个标准兼容的64位double
类型或没有。如果double
与float
完全相同,则有几种解决方案:
- 编写或使用
- 或者如果
double
在8位MCU上太昂贵,你可以创建一个自定义的浮点类型,如40位或48位。 - 或者您可以像这样使用
float-float
算术类型。 - 使用定点类型。由于您总是有4个十进制数字,因此这可能最适合您。
- 您可以使用Q26.6或Q25.7二进制格式以获得更好的算术性能
- 或者最好使用缩放后的十进制类型,最后4位数字作为小数部分,以获得更好的十进制数学输出。在某些情况下,您也可以将后4位十进制数字和整数部分分开存储,但要小心使用此实现。
double
数学库。你可以在本题中或在
相关文章:
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 使用提升将数据从 PyObject 复制到浮点数 *
- 使用浮点数和双精度数的非常小数字的数学
- 使用英特尔内联函数将打包的 8 位整数乘以浮点数向量
- 如何在 c++ 中将小数点后两位数的浮点数分配给另一个浮点数
- 返回浮点数的小数位数
- txt 文件中浮点数的最大和最小值
- 为什么 std::cout 打印浮点数、双精度和长双精度到相同的小数精度?
- 在数学上将浮点数四舍五入到 N 位小数
- 从浮点数中删除小数部分但保留类型的有效方法
- 小数浮点数缺少除法 (C++)
- 如何计算C++浮点数中的小数位数
- 将浮点数四舍五入为2位小数,将其写入文本文件
- 使用 6 位设置浮点数的小数部分
- 将浮点数截断为前导N位小数
- 精确地提取浮点数的小数部分
- 将浮点数打印为小数并修复错误输出
- 如何计算具有 n 位小数的浮点数