2

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

Juha P
  • 295
  • 1
  • 6
  • So this is going to sound stupid... but you have a lot of unintended conversion going on in your code. `4.5` is a `double` not a `float`, ditto `1` is an integer. If you want to keep conversion to a minimum I'd suggest suffixing those with `f` to tell the compiler to make them float constants. – Mgetz Aug 22 '22 at 13:39
  • 1
    Replace `abs` with `std::abs`. Still have the problem? – Eljay Aug 22 '22 at 13:41
  • 3
    somewhat related: [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – 463035818_is_not_an_ai Aug 22 '22 at 13:41
  • 1
    Check [this answer](https://stackoverflow.com/a/21393170/580083). Relevant quote: _"C didn't provide any overloads: `abs` took an `int`, and was declared in ``"_. Without `std`, it seems that this "C" version is called and rounding occurs. – Daniel Langr Aug 22 '22 at 13:45
  • 3
    This is such a good example of why, even using it in a limited scope, using namespace std is a bad idea. – user438383 Aug 22 '22 at 13:50
  • 2
    @user438383 the common mantra is "never in headers, can be ok in source", this is a nice counter example – 463035818_is_not_an_ai Aug 22 '22 at 13:52
  • @Mgetz yes, I forgot to edit those values to floats (copied from Octave output box) but result is same even with all set floats. – Juha P Aug 22 '22 at 15:45
  • @Eijay latter result data shows for std::abs(). – Juha P Aug 22 '22 at 15:45
  • @DanielLangr yes, int-int and float-float pairs are OK but float-int and int-float pairs gets rounded. – Juha P Aug 22 '22 at 15:46

1 Answers1

12

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?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • In addition, when `using namespace std` is given already before `#include "test999.h"` in main module, inheritance is correct and abs() works properly. `#include #include using namespace std; #include "test999.h" int main(){...} ` – Juha P Aug 23 '22 at 05:27