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