There is a related question but I believe it doesn't answer this question.
Looking at std::abs
and std::fabs
documentation they seems to have exactly the same behaviour. As a personal note, it appears to me that std::fabs
is preferable because it mitigates the ambiguity with the std::abs(int)
definition in <cstdlib>
(See note).
So my question is: besides the std::abs(int)
potential ambiguity, is there any difference at all between std::abs
and std::fabs
when applied to floating point values?
In standard-conforming code that has included cmath
and only calls std::abs
on float
s, double
s, and long double
s, there is no difference. However, it is instructive to look at the types returned by std::abs
on various types when you call it with various sets of header files included.
On my system, std::abs(-42)
is a double
if I've included cmath
but not cstdlib
, an int
if I've included cstdlib
, and it produces a compilation error if I've included neither. Conversely, std::abs(-42.0)
produces a compilation error (ambiguous overload) if I've included cstdlib
but I haven't included cmath
or a different compilation error (never heard of std::abs
) if I've included neither.
On my platform, std::abs('x')
gives me a double
if I've included cmath
or an int
if I've included cstdlib
but not cmath
. Similar for a short int
. Signedness does not appear to matter.
On my platform, the complex
header apparently causes both the integral and the floating-point overloads of std::abs
to be declared. I'm not certain this is mandated; perhaps you can find an otherwise reasonable platform on which std::abs(1e222)
returns infinity with the wrong set of standard headers included.
The usual consequence of "you forgot a header in your program" is a compilation failure complaining of an undefined symbol, not a silent change in behaviour. With std::abs
, however, the result can be std::abs(42)
returning a double
if you forgot cstdlib
or std::abs('x')
returning an int
if you didn't. (Or perhaps you expected std::abs
to give you an integral type when you pass it a short
? Then, assuming my compiler got its promotion and overload resolution right, you had better make sure you don't include cmath
.)
I have also spent too much time in the past trying to work out why code like double precise_sine = std::sin(myfloat)
gives imprecise results. Because I don't like wasting my time on these sorts of surprises, I tend to avoid the overloaded variants of standard C functions in namespace std
. That is, I use ::fabs
when I want a double
to be returned, ::fabsf
when I want a float
out, and ::fabsl
when I want a long double
out. Similarly for ::abs
when I want an int
, ::absl
when I want a long
, and ::absll
when I want a long long
.
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