错误的Visual C浮动/双转换?
-
25-09-2019 - |
题
在Visual C ++ i的一个C写下面的示例++程序:
float f1 = 42.48f;
double d1 = 42.48;
double d2 = f1;
我编译的程序与Visual Studio 2005。 在调试器我看到以下值:
f1 42.480000 float
d1 42.479999999999997 double
d2 42.479999542236328 double
D1由我knowledege是确定的,但D2是错误的。
使用时出现的问题,以及/ FP =精确与/ FP =严格与/ FP =快。
请告诉我这里的问题?任何提示如何避免这个问题?这导致严重的数值问题。
解决方案
这是不是与VC ++或任何类似的问题 - 它的浮点数字是如何存储在计算机上的一个根本问题。有关详细信息,请参阅 IEEE-754 。
的问题是,从浮到双转换完成,从而把从双回浮结果完全相同的浮点值,您开始使用。我不知道的身边的精度损失任何方式,但只使用了一倍,当你需要较长的精度。这可能是试图round
转换后的浮动小数点后两位将它设置为正确的值,但我不知道这一点。
其他提示
在f1
和的值在d2
值都代表完全相同的编号。这个数字是不完全42.480000,也不是完全相同42.479999542236328,虽然它确实有一个十进制表示终止。当显示的花车,你的调试视图合理四舍五入在浮动的精度,并显示双打它四舍五入在双精度时。所以你看到的两倍左右,当您转换和神秘值的许多显著的数字显示为双。
d1
包含一个更好的近似,以4.48比神秘值,因为d1
包含4.48最接近双,而f1
和d2
仅包含最接近的浮点值至4.48。你是怎么想到d2
遏制? F1不能“记住”,它的“真应该是” 4.48,这样,当它转换为DOUBLE它变得“更准确”。
要避免它的方式取决于你的意思是它严重的数值问题。如果问题是,D1和D2不比较相等,你认为他们应该,那么答案是包括在您的比较小的耐受性,例如,以替换d1 == d2
:
fabs(d1 - d2) <= (d2 * FLT_EPSILON)
这仅仅是一个例子,但是,我还没有检查它是否与此案。你必须选择一个宽容,你的作品,你可能还需要对大量的边缘情况的担心 - D2可能是零,要么值可能是无穷大或NaN,可能还有其他
如果问题是,D2是不是你的算法来产生准确的结果足够精确的值,那么你必须避免float
值,和/或使用多个数值稳定的算法。
有什么错这里发生了什么。
由于的浮点数被在存储器所代表的方式,42.479999999999997是42.48最接近表示的是一个双可以有。
阅读本文: http://docs.sun.com/source/806-3568/ncg_goldberg。 HTML
它解释发生的事情在那里。有不幸的是什么,你可以做它的存储。