17

我有一个double打印的 as0.000000并且我试图将它与 进行比较0.0f,但没有成功。为什么这里有区别?确定您的双倍是否为零的最可靠方法是什么?

4

4 回答 4

20

要确定它是否足够接近零以使其打印0.000000到小数点后六位,例如:

fabs(d) < 0.0000005

不过,处理浮点计算中的小错误通常会变得相当复杂。

如果您想更好地了解您所获得的价值,请尝试使用%g而不是%f.

于 2011-08-10T09:38:52.050 回答
4

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

于 2011-08-10T09:39:47.697 回答
4

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

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

于 2011-08-10T09:40:02.563 回答
1

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

这些数字低于浮点数的 FLT_MIN 和双精度数的 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".

非规范化通常还意味着计算中的性能损失。但是,您不能禁用它们,否则此类代码仍可能产生除以零浮点异常(如果启用):

float getInverse(float a, float b) {
    if (a != b)
        return 1.0f / (a-b); // 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;
}
于 2013-11-26T11:21:40.833 回答