错误的Visual C浮点/双精度转换? 在Visual C++中,我在C++程序中写下了以下示例: float f1 = 42.48f; double d1 = 42.48; double d2 = f1;

错误的Visual C浮点/双精度转换? 在Visual C++中,我在C++程序中写下了以下示例: float f1 = 42.48f; double d1 = 42.48; double d2 = f1;,c,floating-point,visual-studio-2005,double,floating-accuracy,C,Floating Point,Visual Studio 2005,Double,Floating Accuracy,我用VisualStudio2005编译了这个程序。 在调试器中,我看到以下值: f1 42.480000 float d1 42.479999999999997 double d2 42.479999542236328 double 据我所知,d1是可以的,但d2是错的 使用/fp=precise和/fp=strict以及/fp=fast时都会出现问题 这里有什么问题?有什么提示可以避免这个问题吗?这会导致严重的数值问题。这不是VC++或类似的问题,而是浮点数字如何存储在计算机

我用VisualStudio2005编译了这个程序。 在调试器中,我看到以下值:

f1  42.480000   float
d1  42.479999999999997  double
d2  42.479999542236328  double
据我所知,d1是可以的,但d2是错的

使用/fp=precise和/fp=strict以及/fp=fast时都会出现问题


这里有什么问题?有什么提示可以避免这个问题吗?这会导致严重的数值问题。

这不是VC++或类似的问题,而是浮点数字如何存储在计算机上的基本问题。有关详细信息,请参阅


问题在于,从float到double的转换是这样完成的,即从double到float的转换会产生与开始时完全相同的float值。我不知道有什么办法可以避免精度的损失,除非在需要更高精度时只使用双倍。可能是尝试将转换后的浮点值四舍五入到小数点后两位会将其设置为正确的值,但我不确定这一点。

这里发生的事情没有错

由于浮点数字在内存中的表示方式,42.47999999997是双精度浮点数字中最接近42.48的表示形式

阅读本文:


它解释了那里发生的事情。不幸的是,您对它的存储无能为力。

f1中的值和d2中的值都表示完全相同的数字。这个数字不完全是42.480000,也不完全是42.47999542236328,尽管它有一个终止的十进制表示。显示浮点时,调试视图以浮点的精度舍入,而显示双倍时,则以双倍的精度舍入。所以当你们转换并显示为双精度时,你们会看到两倍于神秘值的有效数字

d1
比神秘值更接近4.48,因为
d1
包含最接近4.48的双精度浮点值,而
f1
d2
仅包含最接近4.48的浮点值。您希望
d2
包含什么内容?f1不能“记住”它“真的应该”是4.48,所以当它转换成双倍时,它会变得“更准确”

避免它的方法取决于你指的是什么严重的数值问题。如果问题是d1和d2不相等,而您认为它们应该相等,那么答案是在比较中包含一个小公差,例如,将
d1==d2
替换为:

fabs(d1 - d2) <= (d2 * FLT_EPSILON)
fabs(d1-d2)+1链接到“每个计算机科学家都应该知道的浮点运算”