可能的重复项:
我应该如何进行浮点比较?
不建议在C++中比较双精度和双精度文字的相等性,因为我想它是编译器依赖的?
更准确地说,比较硬编码的双精度(源代码中的文字)和应该计算的双精度是不行的,因为计算结果的最后一个数字可能因编译器而异。这不是标准化的吗?
我听说高德纳的TeXbook中提到了这一点,对吗?
如果这一切都是真的,解决方案是什么?
你有点误解了这个建议。关键是浮点计算并不精确。发生舍入误差,精度逐渐丢失。拿一些简单的事情来说1.0/10.0
.结果应该是 0.1
,但事实并非如此,因为0.1
不能以浮点格式精确表示。所以实际结果会略有不同。无数其他操作也是如此,因此这一点与常量双精度无关。这与不期望结果准确有关。如果你执行一些计算,结果应该是1.0
,那么你不应该测试它是否相等1.0
,因为舍入误差可能意味着它实际上是0.9999999997
出来的。
所以通常的解决方案是 测试结果是否足够接近1.0
.如果它很接近,那么我们假设"它足够好",并表现得好像结果是 1.0。
底线是,浮点值很少使用严格相等。相反,您应该测试两个值之间的差异是否小于某个小值(通常称为 epsilon)
您正在谈论的问题是由于舍入错误造成的,并且每个浮点数都会发生。您可以做的是定义一个 epsilon 并查看两个浮点数之间的差异是否小于此值。例如:
double A = somethingA();
double B = somethingB();
double epsilon = 0.00001;
if (abs(A - B) < epsilon)
doublesAreEqual();
[编辑] 另请参阅此问题:浮点数和双重比较的最有效方法是什么?
关键问题是浮点运算的工作原理 - 它包括四舍五入,这可能导致比较错误的相等性。这适用于所有浮点数,无论变量是否声明为const
。
如果您进行浮点计算并且需要与某些固定值进行比较,则使用 epsilon 值来考虑精度误差总是更安全的。
例:
double calcSomeStuf();
if ( calcSomeStuf() == 0.1 ) { ...}
是个坏主意
然而:
const double epsilon = 0.005
double calcSomeStuf();
if ( abs(calcSomeStuf() - 0.1) < epsilon ) { ...}
要安全得多(特别是考虑到 0.1 不能完全表示为双精度的事实)
这是必要的,因为当累积浮点运算时会发生舍入误差,并且由于浮点的性质,并非所有数字都可以精确表示