When do I use fabs and when is it sufficient to use std::abs?
I assume that abs
and fabs
are behaving different when using math.h
. But when I use just cmath
and std::abs
, do I ha开发者_运维问答ve to use std::fabs
or fabs
? Or isn't this defined?
In C++, it's always sufficient to use std::abs
; it's overloaded for all the numerical types.
In C, abs
only works on integers, and you need fabs
for floating point values. These are available in C++ (along with all of the C library), but there's no need to use them.
It's still okay to use fabs
for double
and float
arguments. I prefer this because it ensures that if I accidentally strip the std::
off the abs
, that the behavior remains the same for floating point inputs.
I just spent 10 minutes debugging this very problem, due to my own mistake of using abs
instead of std::abs
. I assumed that the using namespace std;
would infer std::abs
but it did not, and instead was using the C version.
Anyway, I believe it's good to use fabs
instead of abs
for floating-point inputs as a way of documenting your intention clearly.
There is one more reason to recommend std::fabs
for floating-point inputs explicitly.
If you forget to include <cmath>, your std::abs(my_float_num)
can be std::abs(int)
instead of std::abs(float)
. It's hard to notice.
"abs" and "fabs" are only identical for C++ float types, when they can be translated without ambiguous overload messages.
I'm using g++ (g++-7).
Together with template usage and especially when using mpreal there are cases with hard "ambiguous overload" messages - abs(static_cast<T>(x))
isn't always solving that.
When abs is ambiguous, there are chances that fabs is working as expected. For sqrt I found no such simple escape.
Since weeks I'm hard struggling on C++ "not existing problems". I'm updating an old C++ program to C++14 for more and better template usage than possible before. Often the same template parameter may be actual any standard float or complex type or a class type. Why ever, long double acted somewhat more sensible than other types. All was working, and I had included mpreal before. Then I was setting my default float type to mpreal and got a deluge of syntax errors. That gave thousands of ambiguous overloads e.g. for abs and sqrt, crying for different solutions. Some were needing overloaded help functions, but outside of a template. Had to replace individually a thousand usages of 0.0L and 1.0L with the exact constant type using Zero or One or a type_cast - automatic conversion definition impossible because of ambiguities.
Up to May I found the existing of implicit conversions very nice. But much simpler it would be without any, and to have typesave constants with safe explicit type_casts to any other standard constant type.
精彩评论