如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?

How to keep c++ from adding extra decimals when casting from float to double (not for IO)?

本文关键字:添加 IO 小数 适用于 不适用 c++ 何防止 浮点型 转换 双精度型      更新时间:2023-10-16

我面临的问题是因为我正在使用一个库,当输入float时,它会在内部执行一些操作,将浮点数转换为双精度并将许多小数添加到不正确的数字中。我的意思是,根据双精度和浮点数的表示方式以及投掷时自然发生的情况是正确的,但这不适合我的应用程序。我有16.3float,我需要像double一样16.3

我正在尝试在将值传递给库以控制该转换之前将浮点数转换为双倍 U,但到目前为止,我还没有找到一种直接的方法。我只想知道是否有可能将 16.3 从float投到double并因此获得相同的 16.3。

float f_var = 16.3;            // f_var is 16.3
double d_var = (double)f_var;  // d_var shall be also 16.3, not 16.299999237060547

在C++中甚至有适当的方法来做到这一点吗?或者我将不得不做这样的事情:

char float_buf[10];
float f_var = 16.3;
sprintf(float_buf, "%.2f", f_var);
double d_var = atof(float_buf);

因为这有效,但我想看看在 c++ 中是否有一种"适当"的方法。

SO中有另一个建议的解决方案的响应,但它涉及乘法和除法,我也想避免。

这不是为了显示或任何输入/输出操作或转换为字符串,我知道该怎么做,并且有很多关于它的信息。此外,我并不是想理解"为什么"会发生这种情况,也有很多关于这方面的信息。

此外,SO中可能导致此问题标记为重复的大多数答案都不适用于C++,它们主要针对C#,Java JS,Objective C等。对于我为 C/C++ 找到的少数几个,他们中的大多数都在用printfcout处理 IO 的这个问题,其他人只解释为什么会发生这种情况,这也是没有用的。如果您确实在C++中对此有副本,请注明。如果真的是,我会很高兴将其标记为重复。

谢谢!

这个答案假设IEEE浮点数。

机器数据类型(如float)包含有限数量的位,因此只能表示有限数量的值。唉,16.3碰巧不是其中之一。

float f_var = 16.3;

f_var的值现在是 (1) 可表示为单个精度浮点数和 (2) 尽可能接近16.3的数字。这个数字恰好是16.299999237060546875。这是最接近16.3的一个。下一个较大的可表示数是16.3000011444091796875,它离得更远。如果您好奇,这两个二进制表示是0100000110000010011001100110011001000001100000100110011001100111的。它们仅在最后一点不同。

double d_var = (double)f_var;

你瞧,d_var的值现在是完全相同的数字16.299999237060546875

这是最接近16.3的可能double数字吗?地狱不!

double可以准确地表示16.300000000000000710542735760100185871124267578125,它更接近16.3然后16.299999237060546875

但是d_var为什么要采用这个更精确的值呢?它已经16.299999237060546875显示,现在它非常忠实地16.299999237060546875。如果希望它更精确,请为其分配一个更精确的值。它不是有情众生,也不知道你的意思16.29999923706054687516.3

从哪里可以得到如此精确的值?

好吧,人们可以任意决定所有有趣的数字在小数点后不超过一位数字,并且在此之后有无限个零。(为什么人们会认为这超出了我的范围,但我正在玩)。如果是这种情况,那么

d_var = round(d_var * 10)/10

会将数字四舍五入为非常接近小数点后有一个十进制数字的数字,以及无限个零的数字。如果我们用16.299999237060546875做这个技巧,它会变得16.300000000000000710542735760100185871124267578125

如果您对小数点后两位数的数字感兴趣,请将 10 替换为 100,依此类推。但是,在这一点上,您应该问问自己浮点类型是否是适合这项工作的工具。也许您需要定点十进制数?

另一方面,如果您对最初具有任何位数的数字感兴趣,那么您必须提供该位数,并可能将其与数字本身一起记住。在这一点上,你应该更加努力地问自己上述问题。