比较c ++中的浮点数

Comparing floats in c++

我正在通过教程学习 C++,有人告诉我在 C++ 中比较浮点数可能会非常令人困惑。例如,在下面的代码中:

#include <iostream>

using namespace std;

int main()
{
    float decimalNumber = 1.2;
    
    if (decimalNumber == 1.2){
        cout << "Equal" << endl;
    }else{
        cout << "Not equal" << endl;
    }

    return 0;
}

我会得到“不等于”。我同意这一点。导师告诉我们,如果我们需要比较浮点数,我们可以使用 > 到最近的数字。 (这不是很精确)。我在 google 中搜索了不同的方法来比较浮点数,并且我得到了很多复杂的方法。

然后我自己创建了一个程序:

#include <iostream>

using namespace std;

int main()
{
    float decimalNumber = 1.2;
    
    if (decimalNumber == (float)1.2){
        cout << "Equal" << endl;
    }else{
        cout << "Not equal" << endl;
    }

    return 0;
}

像上面那样进行类型转换后,我得到了“等于”。

我想知道的是,我是否应该在我的所有程序中都使用上述方法来比较浮点数?这有什么缺点吗?

注意 :我知道一个数字在内存中是如何精确表示的,以及 0.1 + 0.2 !- 0.3 是如何描述的SO Question。我只是想知道我可以用上面的方法检查两个浮点数是否相等吗?

在某种程度上,第二个示例起作用的原因纯属偶然。

需要考虑的一些因素:

  1. 当比较的两边都是float类型时,编译器可能更有可能“优化掉”比较,这样它就发生在编译过程中。它可以查看文字并意识到这两个数字在逻辑上是相同的,即使在运行时它们可能在较低的精度级别上有所不同。

  2. 当比较的两边都是 float 类型时,它们具有相同的精度,因此如果您以相同的方式创建值(此处为文字) , 较低精度水平的任何错误都可能相同。当其中之一是 double 时,您在末尾会有额外的错误位,从而导致比较失败。如果您通过 0.6 + 0.6 创建了一个,那么结果也可能不同,因为错误传播的方式不同。

一般情况下,不要依赖这个。当你的浮点数包含不能用二进制精确表示的数字时,你无法真正预测你的浮点数有多“准确”。如果您需要松散的值比较,您应该坚持使用 epsilon 范围比较(在适当的情况下),即使直接比较在没有它的情况下偶尔似乎“有效”。

如果您实际上不需要 浮动 点,一个好的方法是使用固定点。该语言中没有内置的定点类型,但这没关系,因为您可以通过一些算术简单地模拟它们。很难知道您的用例是什么,但如果您只需要一位小数,则可以存储 int decimalNumber = 12(即将小数点移动一位),并在需要显示时除以十。两个 int 的值 12 总是比较好。

金钱就是一个很好的例子:以便士(或十分之一便士)计算,而不是以英镑计算,以避免在骗取客户现金时出现错误。

与浮点变量相比的浮点数在 C++ 中默认被视为 double。您需要使用 f 后缀来告诉编译器该数字是浮点数而不是 double。举个例子:

#include <iostream>

int main(void) {
    float dec = 1.2;

    if (dec == 1.2f)
        std::cout << "Equal";
    else
        std::cout << "Unequal";
    
    return 0;
}

它将产生 Equal。 OTOH,如果你不使用 f 后缀,比较将等同于:

if (dec == 1.199999999999999956) // 1.2 converted into double

The thing I want to know is that should I use the above way to compare floats in all of my programs?

取决于上下文。相等比较很少对浮点数有用。

但是是的,无论是相等性还是关系性比较,都应该比较相同类型的浮点对象,而不是混合使用 float 和 double。

Does this have some cons?

浮点计算可能有错误。结果可能不是您所期望的。当有错误时,相等比较是没有意义的。