2016-12-06 136 views
1

关于浮点数比较有大量的文档和讨论。但是对于我来说,目前尚不清楚能否保证直接比较数字在所有编译器和平台上都能正常工作?精确值的双/浮点比较

double x = 1.; 
if (1. == x) 
{ 
    //do something 
} 

我们总是会输入if块吗?

编辑:

这里什么比较正确的是(永久有效)?这一个?:

double x = 1.; 
if (std::abs(1. - x) < std::numeric_limits<double>::epsilon()) 
{ 
    //do something 
} 
+4

一些浮点值,例如'1.0',可以用IEEE浮点格式(这是最常用的格式)精确表示。所以你的比较可以在你显示的确切代码中正常工作。但是,尝试在'x'上执行一些操作,*应该*将其保留为'1.0',然后重试比较,并且很可能不起作用。 –

+0

听起来像你应该阅读这个:https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –

+0

为了解决你的问题的第二部分,不,'std :: numeric_limits : :epsilon()'不打算像那样使用。 'std :: numeric_limits :: epsilon()'是格式精度的度量,它不是前面计算精度的度量。如果前面的计算可能产生了0.125的绝对误差,并且您希望在数学计算产生1.0时检测出没有误报的测试,请使用std :: abs(1.x)<= 0.125'。在所有情况下,无论上下文如何,RHS都没有可用的神奇价值。 –

回答

0

如果你有两个精确的浮点值,你不必担心,比较它们可能会违反你的期望。问题是你怎么知道你的价值观是确切的?

对于所提供的例子,你可以非常有信心x == 1.0将评估为true - 我个人不会考虑支持,将不能在该测试的任何平台。然而,如果不能确切地告诉你应该停止依赖比较的结果,那么就有可能逐渐复杂化你的例子。

1

是的,像这样的直接比较 - 无需干预操作 - 将始终有效。为浮点文字存储的位模式是浮点系统可以表示的最接近的模式(几乎总是IEEE-754)。所以测试1.0 == 1.0将始终工作,因为位模式是1.0;和0.3 == 0.3始终工作,因为在两种情况下,位模式 - 尽管不完全是0.3 - 是最接近0.3的表示数。

至于epsilon的东西,远离机器epsilon,直到你真正知道它代表什么和它是什么。机器epsilon是相对的,不是绝对的;并用它来比较“足够接近”需要了解各种操作可能引入多少错误。有趣的是,在你的具体情况下,这两个测试实际上是相同的:只有正好1.0才能通过测试。