Equation with abs() gives wrong answer (gcc/g++)

Viewed 142

Somehow I get wrong result from equation which involves library function abs(). Here's my code where the issue is present:

main.cpp -------------------------------------

#include <iostream>
#include <cmath>

#include "test999.h"

using namespace std;

int main()
{
    float n = 11;
    ak r;

    r = test(n);
    printf("\n");
    for(int i = 0; i < n; i++){
        printf("r.yp[%d] = %3.7f \n", i, r.yp[i]);
    }

    return 0;
}

test999.h ---------------------------------------

struct ak{
    float yp[20];
};

ak test(int n){

    float u[] = {0, 0, 0, 0, 0, 0, 0, 0.5, 4.5, 35, 10, 25, 40, 55};
    ak r;
    float a, b;

    for(int i = 0; i < n; i++){
       a = abs(u[i+3] - u[i+2]);
       b = abs(u[i+1] - u[i]);

       printf("i = %d   a = u[%d](%2.4f) - u[%d](%2.4f) = %2.4f \n        b = u[%d]-u[%d] = %2.4f (%2.4f - %2.4f) \n", i, i+3, u[i+3], i+2, u[i+2], a, i+1,  u[i+1], i, u[i], b);

       if ((a+b) != 0.0f){
          r.yp[i] = (a * u[i+1] + b * u[i+2]) / (a+b);
       }
       else{
          r.yp[i] = (u[i+2] + u[i+1]) / 2.0f;
       }
       printf("yp[%d] = %2.4f \n\n", i, r.yp[i]);
    }
    return r;
}

and it results wrong value for equation of abs(0.5)-0.0 (case i=4) and abs(35.0)-4.5 (case i=6):

enter image description here

Changing equation to use std::abs() calculates correctly:

enter image description here

If I move everything to main.cpp module both cases works so, is it just that because of I have made defect code ... or rounding from 0.5 to 0.0 happened somewhere I should have taken into account... ?

1 Answers

There is std::abs(int) and there is std::abs(float). The former is inherited from C abs(int). In C there is no overload for floating points, it is called fabs (also available as std::fabs).

You tripped over using namespace std; obfuscating what function is actually called. Note that you have it in main, but not in the header, which is actually good, but it still does harm in main, because once you place all code in main, suddenly a different function gets called. Without using namespace std;, abs(some_float) calls ::abs(int). With using namespace std;, abs(some_float) calls std::abs(float).

Note that the headers inherited from C are allowed but not guaranteed to introduce the names in the global namespace, so you could also get a compiler error.

Replace abs with std::abs and remove using namespace std. For more reasons to not pull in all names from std I refer you to Why is "using namespace std;" considered bad practice?

Related