c++cmath

abs vs std::abs, what does the reference say?


Beware, I am talking about ::abs(), not std::abs()

According to the cplusplus.com website, abs is supposed to behave differently for the stdlib.h C version, if you include <cmath>

Here is an extract from the this page (which deals with ::abs, not std::abs):

double abs (double x); 
float abs (float x); 
long double abs (long double x);
Compute absolute value
/*
Returns the absolute value of x: |x|.
These convenience abs overloads are exclusive of C++. In C, abs is only declared
in  <cstdlib> (and operates on int values). 
The additional overloads are provided in this header (<cmath>) for the integral types: 
These overloads effectively cast x to a double before calculations 
(defined for T being any integral type).
*/

Really???

I have been bitten by this when porting a program to a new platform, since different compilers and standard libraries implementation differ here.

Here is my sample program:

#include <iostream>
//#include <stdlib.h>//Necessary inclusion compil under linux
//You can include either cmath or math.h, the result is the same
//#include <cmath>
#include <math.h>
int main(int argc, const char * argv[])
{
  double x = -1.5;
  double ax = std::abs(x);
  std::cout << "x=" << x << " ax=" << ax << std::endl;
  return 0;
}

And here is the result under MSVC 2010:

Now here is the result under OSX:

And finally the result under Linux:

No clear winner here. I know that an obvious answer is "prefer std::abs to ::abs", but I wonder:


Solution

  • The official references say... it's a mess. Pre-C++11 and C11:

    Roughly speaking, either you included <cmath>, and prefixed all of the uses with std::, or you included <math.h>, and used fabs if you wanted support for floating point (and the various suffixes for types other than int or double).

    C++11 and C11 added a few new twists:

    All in all, the situation has become slightly worse, and my recommendations above still hold. Include either <math.h> and <stdlib.h>, and use abs/fabs and their derivated (e.g. labs, fabsf, etc.) exclusively, or include <cmath>, and use std::abs exclusively. Anything else, and you'll run into portabiity problems.