我在C ++(CodeBlocks)中做某事,但是发现一个奇怪的问题。我将代码发送给了我的朋友(他在DevC ++中对其进行了测试),并且可以正常工作。
我尝试了以下两个代码:

#include <iostream>
#include <math.h>
using namespace std;

int main() //this function works
{
    if (pow(3, 2) + pow(4, 2) == pow(5, 2)) {
        cout << "Works" << endl;
    } else { cout << "Nope" << endl; }
}


但是,然后我像这样更改了主要功能(并且不起作用):

int main() //this function doesn't work
{
    int t1 = 3, t2 = 4, t3 = 5;
    if (pow(t1, 2) + pow(t2, 2) == pow(t3, 2)) {
        cout << "Works" << endl;
    } else { cout << "Doesn't work" << endl; }
}


有人知道出什么问题吗?

最佳答案

除非您告诉我们您的“怪异”错误是什么,否则我假设这是您的第二段代码:


  不起作用


问题是,您正在比较浮点数,因为pow()返回floating pointssee the definition of pow() function

由于Rounding Errors,浮点数学并不精确。诸如9.0之类的简单值无法使用二进制浮点数精确表示,并且浮点数的有限精度意味着操作顺序中的微小变化会改变结果。不同的编译器和CPU体系结构以不同的精度存储临时结果,因此结果将根据环境的详细信息而有所不同。例如:

    float a = 9.0 + 16.0
    float b = 25.0
    if(a == b) // can be false!
    if(a >= b) // can also be false!


甚至

    if( Math.abs(a-b) < 0.00001) // wrong - don't do this


这是一种不好的方法,因为当比较的数字也非常小时,由于“看起来很小”而选择的固定epsilon(0.00001)实际上可能太大。

我个人使用以下方法,

public static boolean nearlyEqual(float a, float b, float epsilon) {
        final float absA = Math.abs(a);
        final float absB = Math.abs(b);
        final float diff = Math.abs(a - b);

        if (a == b) { // shortcut, handles infinities
            return true;
        } else if (a == 0 || b == 0 || diff < Float.MIN_NORMAL) {
            // a or b is zero or both are extremely close to it
            // relative error is less meaningful here
            return diff < (epsilon * Float.MIN_NORMAL);
        } else { // use relative error
            return diff / Math.min((absA + absB), Float.MAX_VALUE) < epsilon;
        }
    }


并且不要忘记阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic

参考:This是我的答案的参考。

编辑:由于OP关于C++的问题,因此这是nearlyEqual()的编辑版本:

#include <iostream>     // std::cout
#include <cmath>        // std::abs
#include <algorithm>    // std::min
using namespace std;

#define MIN_NORMAL 1.17549435E-38f
#define MAX_VALUE 3.4028235E38f

bool nearlyEqual(float a, float b, float epsilon) {
    float absA = std::abs(a);
    float absB = std::abs(b);
    float diff = std::abs(a - b);

    if (a == b) {
        return true;
    } else if (a == 0 || b == 0 || diff < MIN_NORMAL) {
        return diff < (epsilon * MIN_NORMAL);
    } else {
        return diff / std::min(absA + absB, MAX_VALUE) < epsilon;
    }
}

int main(void) {
    float t1 = 3.0, t2 = 4.0, t3 = 5.0, epsilon = 0.0000000001; // don't use int here!
    if (nearlyEqual((pow(t1, 2) + pow(t2, 2)), pow(t3, 2), epsilon)) {
        cout << "Works" << endl;
    } else {
        cout << "Doesn't work" << endl;
    }
    return 0;
}


输出为:


  作品


编译器:Cygwin C ++编译器。

Cygwin版本:1.7.25

关于c++ - CodeBlocks C++错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30628945/

10-11 22:51