When do I use fabs and when is it sufficient to use std::abs?

C++math.hCmath

C++ Problem Overview


I assume that abs and fabs are behaving different when using math.h. But when I use just cmath and std::abs, do I have to use std::fabs or fabs? Or isn't this defined?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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.

Solution 3 - C++

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.

Solution 4 - C++

"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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmathView Question on Stackoverflow
Solution 1 - C++Mike SeymourView Answer on Stackoverflow
Solution 2 - C++Alan TuringView Answer on Stackoverflow
Solution 3 - C++Kenichi Hidai View Answer on Stackoverflow
Solution 4 - C++BS3View Answer on Stackoverflow