比较C中的浮点数

我有一个打印为0.000000double ,我试图将它与0.0f进行比较, 0.0f成功。 为什么这里有区别? 什么是最可靠的方法来确定你的双倍是零?

要确定它是否足够接近零,它将打印为0.000000到六位小数,如下所示:

 fabs(d) < 0.0000005 

但是,处理浮点计算中的小的不准确性通常会变得非常复杂。

如果您想更好地了解您的价值,请尝试使用%g而不是%f打印。

你可以做一个范围。 像-0.00001 <= x <= 0.00001

这是现代计算机上浮点运算的基本问题。 它们本质上是不精确的,无法可靠地进行比较。 例如,语言ML明确禁止对实际类型进行相等比较,因为它被认为太不安全了。 另请参阅David Goldberg关于此主题的优秀(如果有点长且以数学为导向) 论文 。

编辑:tl;博士:你可能做错了。

此外,一个经常被忽略的浮点数特征是非规范化数。 这是具有最小指数的数字,但不适合0.5-1范围。

对于float,这些数字低于 FLT_MIN,对于double,这些数字低于 DBL_MIN。

使用阈值的常见错误是比较两个值,或使用FLT_MIN / DBL_MIN作为限制。

例如,这将导致非逻辑结果(如果您不了解非正规):

 bool areDifferent(float a, float b) { if (a == b) return false; // Or also: if ((a - b) == FLT_MIN) return true; } // What is the output of areDifferent(val, val + FLT_MIN * 0.5f) ? // true, not false, even if adding half the "minimum value". 

非正规数通常也意味着计算中的性能损失。 但是,您无法禁用它们,否则此类代码仍可能产生DIVIDE BY ZERO浮点exception(如果已启用):

 float getInverse(float a, float b) { if (a != b) return 1.0f / (ab); // With denormals disabled, a != b can be true, but (a - b) can still be denormals, it'll rounded to 0 and throw the exception return FLT_MAX; }