fabs is one of a family of type-specific names from C. The C++ standard libraries provide these names, fabsf for float, fabs for double and fabsl for long double, for compatibility with C, so that barring other issues C code that uses these names can be compiled as C++. However, the C++ library provides corresponding overloads of the single name abs, which one should use in C++. There is an issue with abs, namely that the overloads for integral argument types reside in (or for the name placed in the std namespace, in ). So, for using abs one should better include both and . And since in C++17 and later the header provides some functions that are not provided by , if one writes a wrapper to include standard library numerical stuff headers then it should best include also . Answer from alfps on reddit.com
🌐
Reddit
reddit.com › r/cpp_questions › difference between abs() and fabs(), and can i replace with each other in the program?? and abs() fn is kinda not working.....
r/cpp_questions on Reddit: Difference between abs() and fabs(), and can i replace with each other in the program?? And abs() fn is kinda not working.....
November 26, 2019 - fabs is one of a family of type-specific names from C. The C++ standard libraries provide these names, fabsf for float, fabs for double and fabsl for long double, for compatibility with C, so that barring other issues C code that uses these ...
Top answer
1 of 2
15

In standard-conforming code that has included cmath and only calls std::abs on floats, doubles, and long doubles, 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.

2 of 2
0

Is there any difference at all between std::abs and std::fabs when applied to floating point values?

No there is not. Nor is there a difference for integral types.

It is idiomatic to use std::abs() because it is closest to the commonly used mathematical nomenclature.

Discussions

c++ - What's the difference between abs and fabs? - Stack Overflow
I checked the difference between abs and fabs on python here As I understand there are some difference regarding the speed and the passed types, but my question related to native c++ on V.S. Rega... More on stackoverflow.com
🌐 stackoverflow.com
Fabs and abs
Try simply this: [code]#if 1 /* 0 or 1 / #include // for “abs” #include // for “fabs” #else / 0 or 1 / #include // for “std::abs” and “std::fabs” #endif / 0 or 1 */ · You should have got it by now that there’s no “default c++ behaviour” what concerns ... More on root-forum.cern.ch
🌐 root-forum.cern.ch
0
0
July 10, 2012
abs() vs fabs()
Hi, I noticed that the C++ compiler (pgCC 10.3-0 64-bit target on x86-64 Linux -tp shanghai-64) behaves somewhat unexpectedly when trying to compile #include int main() { double a = 5.0; std::abs(a); return 0; } The error message "test-fabs.cpp", line 6: error: more than one instance of overloaded ... More on forums.developer.nvidia.com
🌐 forums.developer.nvidia.com
0
0
December 25, 2010
c++ - abs vs std::abs, what does the reference say? - Stack Overflow
Officially, including ... did very different things. If you included , you used std:: everywhere, or what you got varied from compiler to compiler. C didn't provide any overloads: abs took an int, and was declared in , fabs took double, and ... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 3
49

In C++, std::abs is overloaded for both signed integer and floating point types. std::fabs only deals with floating point types (pre C++11). Note that the std:: is important; the C function ::abs that is commonly available for legacy reasons will only handle int!

The problem with

float f2= fabs(-9);

is not that there is no conversion from int (the type of -9) to double, but that the compiler does not know which conversion to pick (int -> float, double, long double) since there is a std::fabs for each of those three. Your workaround explicitly tells the compiler to use the int -> double conversion, so the ambiguity goes away.

C++11 solves this by adding double fabs( Integral arg ); which will return the abs of any integer type converted to double. Apparently, this overload is also available in C++98 mode with libstdc++ and libc++.

In general, just use std::abs, it will do the right thing. (Interesting pitfall pointed out by @Shafik Yaghmour. Unsigned integer types do funny things in C++.)

2 of 3
19

With C++ 11, using abs() alone is very dangerous:

#include <iostream>
#include <cmath>

int main() {
    std::cout << abs(-2.5) << std::endl;
    return 0;
}

This program outputs 2 as a result. (See it live)

Always use std::abs():

#include <iostream>
#include <cmath>

int main() {
    std::cout << std::abs(-2.5) << std::endl;
    return 0;
}

This program outputs 2.5.

You can avoid the unexpected result with using namespace std; but I would adwise against it, because it is considered bad practice in general, and because you have to search for the using directive to know if abs() means the int overload or the double overload.

🌐
Cppreference
en.cppreference.com › w › cpp › numeric › math › fabs.html
std::abs(float), std::fabs, std::fabsf, std::fabsl - cppreference.com
March 14, 2025 - 1-4) Computes the absolute value of the floating-point value num. The library provides overloads of std::abs and std::fabs for all cv-unqualified floating-point types as the type of the parameter num.(since C++23)
🌐
Quora
quora.com › What-is-the-difference-between-abs-and-fabs-function
What is the difference between abs() and fabs() function? - Quora
In C++, wzxhzdk:6 provides int ... fabs() both return the absolute value of a number, but they differ in types, headers, return types, overloads, and portability....
🌐
CERN
root-forum.cern.ch › t › fabs-and-abs › 14556
Fabs and abs - ROOT - ROOT Forum
July 10, 2012 - in cint it seems that abs and fabs are different function root [6] abs(1.2234234) (const int)1 root [7] fabs(1.2234234) (const double)1.22342339999999994e+00 but this is not the behaviour of c++ codepad.org/gM7JzQ2L
🌐
NVIDIA Developer Forums
forums.developer.nvidia.com › accelerated computing › hpc compilers › legacy pgi compilers
abs() vs fabs() - Legacy PGI Compilers - NVIDIA Developer Forums
December 25, 2010 - Hi, I noticed that the C++ compiler (pgCC 10.3-0 64-bit target on x86-64 Linux -tp shanghai-64) behaves somewhat unexpectedly when trying to compile #include int main() { double a = 5.0; std::abs(a); return 0; } The error message "test-fabs.cpp", line 6: error: more than one instance of overloaded function "std::abs" matches the argument list: function "abs(int)" function "std::abs(long double)" argument types are: (double) ...
Find elsewhere
🌐
CodeSpeedy
codespeedy.com › home › difference between fabs and abs function in c++
Difference between fabs and abs function in C++ - CodeSpeedy
September 14, 2022 - The difference between the fabs() and abs() function is that fabs() function is used for floating values and abs() function is used for integer values. abs() function returns the absolute value for the integer.
Top answer
1 of 1
49

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

  • Officially, including <cmath> introduced nothing in ::; all of the functions were in std::. Practically, only export was less respected, and different compilers did very different things. If you included <cmath>, you used std:: everywhere, or what you got varied from compiler to compiler.

  • C didn't provide any overloads: abs took an int, and was declared in <stdlib.h>, fabs took double, and was declared in <math.h>.

  • If you included <math.h> in C++, it's not clear what you got, but since none of the implementers seemed to care about the standard anyway (see the first point above)...

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:

  • <cmath> is now allowed (but not required) to introduce the symbols in :: as well. One more thing which can vary depending on the implementation. (The goal here was to make existing implementations conformant.)

  • C has a new header, <tgmath.h>, which uses compiler magic to make the functions in <math.h> behave as if they were overloaded as in C++. (So it doesn't apply to abs, but only to fabs.) This header had not been added to C++, for the obvious reason that C++ doesn't need any compiler magic for this.

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.

🌐
Cplusplus
cplusplus.com › forum › beginner › 136274
fabs versus abs? - C++ Forum
June 22, 2014 - C++ provides overload of abs() for all arithmetic types. fabs() and labs() are provided for backward compatibility with C, which does not have function overloading and had to have different fucntions for different types.
🌐
Studiofreya
studiofreya.com › 2014 › 07 › 04 › beware-of-the-difference-between-abs-and-stdabs
Beware of the difference between ::abs and std::abs | Studio Freya
July 4, 2014 - If you only use ::abs with floating point variables, you’ll risk an implicit cast to an integral value (short, int, long). This won’t be converted to std::abs even if you include using namespace std; Be safe, use ::fabs, std::abs or std::fabs, but not ::abs.
🌐
SACO Evaluator
saco-evaluator.org.za › docs › cppreference › en › cpp › numeric › math › fabs.html
std::abs(float), std::fabs - cppreference.com
If successful, returns the absolute value of arg (|arg|). The value returned is exact and does not depend on any rounding modes. This function is not subject to any of the error conditions specified in math_errhandling · If the implementation supports IEEE floating-point arithmetic (IEC 60559), ... Between C++11 and C++14, the standard erroneously required std::abs to have overloads for integer types returning double.
🌐
Codecademy
codecademy.com › docs › c++ › math functions › fabs()
C++ (C Plus Plus) | Math Functions | fabs() | Codecademy
April 13, 2025 - Using abs() with floating-point values may cause implicit type conversion and potential precision loss. No, fabs() doesn’t work with complex numbers. For complex numbers, you should use std::abs() from the <complex> header, which calculates the magnitude of a complex number.
🌐
OpenGenus
iq.opengenus.org › fabs-and-abs-in-cpp
Fabs and abs in C++
January 12, 2023 - The main difference between fabs and abs in C++ is the type of input they accept and the type of output they return.
🌐
Coin-or
coin-or.org › CppAD › Doc › abs.htm
AD Absolute Value Functions: abs, fabs
abs and · fabs are not defined for the base types · std::complex<float> or · std::complex<double> because the complex · abs function is not complex differentiable (see complex types faq ). Derivative CppAD defines the derivative of the ·
🌐
Youth4work
youth4work.com › talent › c language › forum › what is the difference between abs() and fabs() functions?
What is the difference between abs() and fabs() functions?
Both functions are to retrieve absolute value. abs() is for integer values and fabs() is for floating type numbers. Prototype for abs() is under the library file < stdlib.h > and fabs() is under < math.h >. 0 Comments · 0 · View all vote's ...
🌐
Vultr Docs
docs.vultr.com › cpp › standard-library › cmath › abs
C++ cmath abs() - Compute Absolute Value | Vultr Docs
September 27, 2024 - Notice the use of fabs() instead of abs() which is more appropriate for floating-point numbers. The abs() function from the C++ <cmath> library is very effective in dealing with absolute values, either for integers with std::abs() or for ...
Top answer
1 of 2
4

I believe I have found a counter example. I post this as a separate answer, because I don't think that this is at all analogous to the case for integers.

In the cases I considered, I missed that it is possible to change the rounding mode for floating point arithmetic. Problematically, GCC seems to to ignore that when he (I guess) optimizes "known" quantities at compile time. Consider the following code:

#include <iostream>
#include <cmath>
#include <cfenv>

double fabsprod1(double a, double b) {
    return std::fabs(a*b);
}
double fabsprod2(double a, double b) {
    return std::fabs(a) * std::fabs(b);
}

int main() {
        std::fesetround(FE_DOWNWARD);
        double a  = 0.1;
        double b = -3;
        std::cout << std::hexfloat;
        std::cout << "fabsprod1(" << a << "," << b << "): " << fabsprod1(a,b) << "\n";
        std::cout << "fabsprod2(" << a << "," << b << "): " << fabsprod2(a,b) << "\n";
#ifdef CIN
        std::cin >> b;
#endif
}

Output differs, depending on whether I compile with

g++ -DCIN -O1 -march=native main2.cpp && ./a.out

or

g++ -O1 -march=native main2.cpp && ./a.out

Notably, it only takes O1 (what I would consider completely reliable) to change the output in a way that does not seem reasonable to me.

With -DCIN the output is

fabsprod1(0x1.999999999999ap-4,-0x1.8p+1): 0x1.3333333333334p-2
fabsprod2(0x1.999999999999ap-4,-0x1.8p+1): 0x1.3333333333333p-2

without -DCIN the output is

fabsprod1(0x1.999999999999ap-4,-0x1.8p+1): 0x1.3333333333334p-2
fabsprod2(0x1.999999999999ap-4,-0x1.8p+1): 0x1.3333333333334p-2

Edit: Peter Cordes (thank you for the comment) pointed out, that this surprising result was due to my failure in telling GCC to respect the change of rounding mode. By building with the following command, the expected results are achieved:

g++ -O1 -frounding-math -march=native main2.cpp && ./a.out

(works with O2 and O3 as well on my machine).

2 of 2
-1

Comparable problem with intregrals (int) :

#include<cmath>

int fabsprod1(int a, int b) {
    return std::abs(a*b);
}
int fabsprod2(int a, int b) {
    return std::abs(a) * std::abs(b);
}
int fabsprod3(int a, int b) {
    return std::abs(std::abs(a) * std::abs(b));
}

Results in (using your options -O3 -std=c++2a -march=cannonlake):

fabsprod1(int, int):
        mov     eax, edi
        imul    eax, esi
        cdq
        xor     eax, edx
        sub     eax, edx
        ret
fabsprod2(int, int):
        mov     eax, edi
        cdq
        xor     eax, edx
        sub     eax, edx
        mov     edx, esi
        sar     edx, 31
        xor     esi, edx
        sub     esi, edx
        imul    eax, esi
        ret
fabsprod3(int, int):
        mov     eax, edi
        cdq
        xor     eax, edx
        sub     eax, edx
        mov     edx, esi
        sar     edx, 31
        xor     esi, edx
        sub     esi, edx
        imul    eax, esi
        ret

https://godbolt.org/z/tf3nZN

This contradicts your statement about "real/floating point" numbers.

Overall you shouldn't expect the compiler to shortcut math problems for you. That being said some optimizations is made possible. Please provide documentation or a comparable example where you see the optimaztion.