在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最接近双,而f1d2仅包含最接近的浮点值至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

它解释发生的事情在那里。有不幸的是什么,你可以做它的存储。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top