为什么在使用 sscanf_s 或 atof 将 char * 转换为 float 时精度会下降?

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

我正在尝试将仅包含浮点值的 char * 转换为 float 类型,但 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

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

Converting char* to float or double

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

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

,你会得到相同的结果
float myValue = 2.10;

我看到评论中的优秀答案丢失了(或者我没有在那里轻松找到它)另一种选择如何处理它。

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

这是Fixed-point arithmetic的特例。

如果您对 "just to solve this" 感兴趣,无需编写太多代码,无论如何都可以使用大数库,即使是 *100 定点变体也很容易编写错误 - 如果这是您第一次和您没有足够的资源来正确执行此操作(建议使用 TDD)。

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


看完你的新评论后,如果"Does this not have a big impact on financial applications?"

答案:不,零影响,没有理智(和专业)的人会创建带有浮动或双精度的财务应用程序。