比较C中的浮点数

时间:2021-04-24 11:34:41

I've got a double that prints as 0.000000 and I'm trying to compare it to 0.0f, unsuccessfully. Why is there a difference here? What's the most reliable way to determine if your double is zero?

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

4 个解决方案

#1


20  

To determine whether it's close enough to zero that it will print as 0.000000 to six decimal places, something like:

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

fabs(d) < 0.0000005

Dealing with small inaccuracies in floating-point calculations can get quite complicated in general, though.

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

If you want a better idea what value you've got, try printing with %g instead of %f.

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

#2


4  

You can do a range. Like -0.00001 <= x <= 0.00001

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

#3


4  

This is fundamental problem with floating point arithmetic on modern computers. They are by nature imprecise, and cannot be reliably compared. For example, the language ML explicitly disallows equality comparison on real types because it was considered too unsafe. See also the excellent (if a bit long and mathematically oriented) paper by David Goldberg on this topic.

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

Edit: tl;dr: you might be doing it wrong.

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

#4


1  

Also, one often overlooked features of floating point number are the denormalized numbers. That's numbers which have the minimal exponent, yet don't fit in the 0.5-1 range.

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

Those numbers are lower than FLT_MIN for float, and DBL_MIN for double.

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

A common mistake with using a threshold is to compare two values, or use FLT_MIN/DBL_MIN as limit.

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

For example, this would lead unlogical result (if you don't know about denormals):

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

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".

Denormals also usually implies a performance loss in computation. Yet, you can not disable them, else such code could still produce a DIVIDE BY ZERO floating point exception (if enabled):

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

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;
}

#1


20  

To determine whether it's close enough to zero that it will print as 0.000000 to six decimal places, something like:

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

fabs(d) < 0.0000005

Dealing with small inaccuracies in floating-point calculations can get quite complicated in general, though.

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

If you want a better idea what value you've got, try printing with %g instead of %f.

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

#2


4  

You can do a range. Like -0.00001 <= x <= 0.00001

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

#3


4  

This is fundamental problem with floating point arithmetic on modern computers. They are by nature imprecise, and cannot be reliably compared. For example, the language ML explicitly disallows equality comparison on real types because it was considered too unsafe. See also the excellent (if a bit long and mathematically oriented) paper by David Goldberg on this topic.

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

Edit: tl;dr: you might be doing it wrong.

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

#4


1  

Also, one often overlooked features of floating point number are the denormalized numbers. That's numbers which have the minimal exponent, yet don't fit in the 0.5-1 range.

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

Those numbers are lower than FLT_MIN for float, and DBL_MIN for double.

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

A common mistake with using a threshold is to compare two values, or use FLT_MIN/DBL_MIN as limit.

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

For example, this would lead unlogical result (if you don't know about denormals):

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

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".

Denormals also usually implies a performance loss in computation. Yet, you can not disable them, else such code could still produce a DIVIDE BY ZERO floating point exception (if enabled):

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

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;
}