为什么使用 sscanf_s 或 atof 将 char * 转换为浮点数时精度会下降

Why is there a loss in precision when converting char * to float using sscanf_s or atof?

本文关键字:浮点数 转换 精度 char sscanf atof 为什么      更新时间:2023-10-16

我正在尝试将仅包含浮点值的字符*转换为浮点类型,但sscanf_s和atof都产生相同的无效结果。

char t[] = "2.10";
float aFloat( 0.0f ), bFloat( 0.0f );
sscanf_s( t, "%f", &aFloat );
bFloat = atof( t );

输出:

aFloat: 2.09999990
bFloat: 2.09999990

当我查看类似的问题试图确定答案时,我尝试了他们的解决方案,但无济于事。

将字符*转换为浮点数或双精度

这里给出的解决方案是包含"stdlib.h",这样做之后,我将对atof的调用更改为显式调用"std::atof",但仍然没有运气。

遗憾的是,并非所有浮点值都可以以二进制形式显式表示。如果你说,你会得到同样的结果

float myValue = 2.10;

我看到评论中的出色答案丢失(或者我在那里不容易找到它)另一种如何处理它的选项。

你应该写,为什么你需要浮点数。如果您偶然碰巧使用货币金额(而不是太大的金额),您可以创建输入值的自定义解析器,并为值输出创建自定义格式化程序,将其读取为 64b 整数 (*100),并在整个应用程序中使用 100*金额值。如果您正在处理非常大量的数字,请使用一些库来处理大数字,或者您可以创建自己的库,处理字符*数字。

这是定点算术的特例。

如果你对"只是为了解决这个问题"感兴趣,不用编码太多,无论如何都要去大数字库,即使是 *100 定点变体也很容易写出错误 - 如果这是你第一次并且你没有足够的资源来正确做到这一点(TDD 建议)。

但一定要了解数字是如何存储在计算机中的,以及为什么浮点/双精度不能代表所有数字。计算机的浮点2.1(内部使用以 2 为底)与人类的1/3类似,如果没有无限个小数位,就不能用 10 为底表示(以及1.0 == 0.99999...以 10 为底)。(谢谢@tobi303)


看完你的新评论,如果"这对金融应用没有太大影响吗?

答:不,零影响,没有人理智(和专业)会用浮动或双倍创建金融应用程序。