CodeBlocks C++ Bug

天大地大妈咪最大 提交于 2019-12-10 11:57:18

问题


I was doing something in C++ (CodeBlocks), but I found a weird problem. I sent my code to my friend (he tested it in DevC++) and it worked. I tried these two codes:

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

But, then I changed the main function like this (and it didn't work):

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

Anyone knows what's the problem ?


回答1:


Unless you tell us what was your "weird" error, I'm assuming that, your second snippet code prints:

Doesn't work

The problem is, you are comparing floating point numbers because pow() returns floating points, see the definition of pow() function.

Floating point math is not exact because of Rounding Errors. Simple values like 9.0 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. For example:

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

Even

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

This is a bad way to do it because a fixed epsilon (0.00001) chosen because it “looks small” could actually be way too large when the numbers being compared are very small as well.

I personally use the following method,

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

And don't forget to read What Every Computer Scientist Should Know About Floating-Point Arithmetic!

Reference: This is the reference of my answer.

Edit: As the OP's problem concerning about C++, so here is the edited version of 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;
}

The output is :

Works

Compiler : Cygwin C++ Compiler.

Cygwin Version: 1.7.25




回答2:


It worked on ideone.com too ! http://ideone.com/3XcY4G

    int main() 
{
    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; }
}



回答3:


Variable types.

double pow (double base     , double exponent);
     float pow (float base      , float exponent);
long double pow (long double base, long double exponent);
     double pow (Type1 base      , Type2 exponent);        // additional overloads

http://www.cplusplus.com/reference/cmath/pow/

try

> int main() {
>     double d1 = 3.0, d2 = 4.0, d3 = 5.0;
>     if(pow(d1,2) + pow(d2,2) == pow(d3,2)) {
>         cout << "Works" << endl;
>     }
>     else {
>         cout << "Nope" << endl;
>     } }

The above doesn't work in VS 2013 either.

I got it to work by using a function

bool CheckPyth(double a, double b, double c) {
  double aa = pow(a,2);
  double bb = pow(b,2);
  double cc = pow(c,2);

  if(aa + bb == cc) {
    return(true);
  }
  else {
    return(false);
  }
}

This seems to indicate it is, like CoryKramer pointed out, a floating point rounding error. He's also right about the d suffix not being valid for double literals, so I changed the code to correct that as well.




回答4:


The problem is that the math.h doesn't work, so I have to use cmath. Second, not int, but float or double.

Code:

#include <iostream>
#include <cmath>

using namespace std;

int main()
{

    float t1 = 3, t2 = 4, t3 = 5;

    if (pow(t1, 2) + pow(t2, 2) == pow(t3, 2)) {
        cout << "PT" << endl;
    }
    else {
        cout << pow(t1, 2) + pow(t2, 2) << endl;
        cout << pow(t3, 2) << endl;
    }

}


来源:https://stackoverflow.com/questions/30628945/codeblocks-c-bug

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!