Different results using the same function from different libraries

Here is the code:

#include <iostream> #include <cmath> using namespace std; int main() { long long int a, b; long long int c; cin >> a >> b; c = abs(a) + abs(b); cout << c; cout << endl; } 

Estimated return of 1000000000000000002 for input of 1000000000000000000 and 2 .

If I try to do this with cmath , it will return 1000000000000000000 , but if I use cstdlib , it will return 1000000000000000002 . Why is this happening?

Also, given that I'm using cmath, shouldn't it work even more correctly?

I am using Linux Mint 18.2 64bit, Eclipse Platform.

+8
c ++ cmath
source share
2 answers

The cmath version is a float one . Therefore, when you only have this one, you actually do the calculations on the floats and convert back to long long at the end. The accuracy of the float is not enough to hold 18 digits, +2 is simply lost.

The cstdlib version is an integer . Which gives the expected result.

As stated in the comments, in C ++ 11 cmath also defines an abs version that accepts integers. However, "these overloads efficiently pass x to double before calculations (defined so that T is any integral type)."

I believe that your compiler should give you a conversion warning if you use -Wall -Wextra or similar flags just by inserting cmath.

+8
source share

If you are using g ++, try compiling both versions with -Wconversion (or -Wfloat-conversion ).

Note that the <cmath> version generates a warning:

main.cpp: 14: 7: warning : conversion to long long int from __gnu_cxx :: __ enable_if :: __ type {aka double} may change its value [-Wfloat conversion] c = abs (a) + abs (b) ;

So far, the version of <cstdlib> compiled without warning.

This is because in <cmath> , abs() is defined as 1 :

 float abs(float); double abs(double); long double abs(long double); 

In <cstdlib> it is defined as 1 :

 int abs(int); long abs(long); long long abs(long long); 

1 Integer versions of abs() defined in <cmath> since C ++ 17.

+5
source share

All Articles