最近我讨论了浮点比较。我的观点总是不直接使用==
比较两个浮点数。
有人指出这不是真的,有些情况下使用==
完全没问题。
我可以想到典型的情况,我检查IEEE 754文字,+-INF
或+-0
,但除此之外,我想不出这不会导致问题的情况。
所以我的问题是:使用==
的浮点数比较有效时会出现什么情况?
答案 0 :(得分:5)
双精度浮点表示(每个数字64位)对于整数最高为+ + 2 ** 53( - + 9,007,199,254,740,992)。如果您使用的是浮点数,但是从整数开始并使用它们进行整数计算,并且您从未通过该限制,那么结果就是精确的,使用==
就完全没问了。
通常可以精确表示的数字是N / M,其中N是整数,M是2的幂。因此,如果您只是进行涉及例如的计算。它们的1 / 4,1 / 2,3 / 4和整数倍也很好,直到达到很大的乘数。
相反,当您处理无法准确表示的数字(例如0.1)时,近似值会导致我产生令人惊讶的结果。问题的一个原因是中间结果可能以更高的精度存储在临时值中,因此公式的结果可能会有所不同,具体取决于您是否明确地将其存储在内存中,并且它也可能根据优化级别而改变。
答案 1 :(得分:1)
以下是浮点相等的有效用法的一些示例:
将某个函数记录为在某些情况下返回HUGE_VAL
,determining whether this happened并result == HUGE_VAL
。
确定双d
是否包含可表示为float
:d == (double)(float)d
的数字。我实际上在我的日常工作中使用它,因为我使用双对来表示double值的间隔和float值的间隔,并且有一些点可以断言浮点数的间隔的边界是很好的。浮动。
确定浮点数y
是否为NaN
:y == y
。
确定带有y
的浮点数y - y == 0.0
is infinity or NaN(有限值y
是否使条件成立,NaN
和无穷大把它变成假的。)
确定是否在浮点数的有效位中设置了一个位,如下例所示,取自this rant。
/* coef is a power of two plus one. */
double t = coef * f;
double o = f - t + t - f;
if (o != 0)
{
...
答案 2 :(得分:0)
浮点数表示使用相应基数(通常为2)的精确值。使用相等性来比较它们是没有错的。
二进制浮点数不能精确地表示所有十进制值,但是,对于大多数小数十进制值,二进制浮点将使用近似值。只要十进制数不超过std::numeric_limits<F>::digits10
,结果表示也在系统内唯一标识(对于某些十进制值,在两个二进制表示之间存在一个小数,在这种情况下,舍入方向应该选择正确的)。
使浮点数成为奇怪的问题是计算导致值的舍入,并且取决于何时发生舍入,假定精确操作是不精确的,并且评估顺序很重要。对舍入值进行算术将相应地增加误差并产生与获得的值不同的值,例如通过从十进制值到二进制浮点的转换。您可能不希望对计算结果使用相等的操作。