Here is some 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;
}
Which supposed to return 1000000000000000002
when I input 1000000000000000000
and 2
.
If I try to do it with cmath
it will return 1000000000000000000
, but if I use cstdlib
it will return 1000000000000000002
. Why is that even happening?
Also considering that I'm using cmath, shouldn't it work even more proper?
I'm using Linux Mint 18.2 64bit, Eclipse Platform.
The cmath version is a float one. So when you only have that one, you actually do the computation on floats and convert back into a long long
at the end. Float precision not being enough to hold 18 digits, the +2 simply gets lost.
The cstdlib version is a integer one. Which gives the expected result.
As pointed out in the comments, in C++11, cmath also defines a version of abs
that takes integers. However, “these overloads effectively cast x to a double before calculations (defined for T being any integral type)”.
I believe your compiler should give you a warning for the conversions if you use -Wall -Wextra
or similar flags while only inclulding cmath.
If you are using g++, try to compile 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 alter its value [-Wfloat-conversion] c = abs(a) + abs(b);
While the <cstdlib>
version compiles without warnings.
That is because, in <cmath>
, abs()
is defined as1:
float abs(float);
double abs(double);
long double abs(long double);
While in <cstdlib>
it is defined as1:
int abs(int);
long abs(long);
long long abs(long long);
1The integer versions of abs()
are defined in <cmath>
since C++17.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With