Skip to content
C++
Library
since C++98
Basic

<cmath>

Standard C++ header providing mathematical functions for floating-point arithmetic, rounding, classification, and error handling.

<cmath>since C++98

The <cmath> header provides the C++ standard mathematical function library β€” a superset of C's <math.h> β€” placing all names in namespace std and adding overloads for float, double, and long double argument types.

Overview

<cmath> is C++'s primary header for floating-point mathematics. It wraps and extends the C <math.h> library, organising its contents into several functional groups:

  • Basic: abs, fabs, fmod, remainder, remquo, fma, fmax, fmin, fdim
  • Exponential / logarithmic: exp, exp2, expm1, log, log2, log10, log1p
  • Power / root: pow, sqrt, cbrt, hypot
  • Trigonometric: sin, cos, tan, asin, acos, atan, atan2
  • Hyperbolic: sinh, cosh, tanh, asinh, acosh, atanh
  • Rounding: ceil, floor, trunc, round, lround, llround, nearbyint, rint, lrint, llrint
  • Floating-point manipulation: frexp, ldexp, modf, scalbn, scalbln, ilogb, logb, nextafter, nexttoward, copysign
  • Classification / comparison: fpclassify, isfinite, isinf, isnan, isnormal, signbit, isgreater, isless, isunordered

Prior to C++11 the header provided only double overloads; C++11 added float and long double overloads for every function, plus the classification macros were promoted to proper function templates. Several functions gained constexpr qualification in C++20 and C++23 (see individual notes below).

Relationship to <math.h>

Including <cmath> is preferred over <math.h> in C++ code. Both ultimately expose the same functions, but <cmath> guarantees placement in namespace std, eliminating naming collisions and enabling argument-dependent lookup. The <math.h> form additionally injects names into the global namespace β€” a behaviour that is implementation-defined for <cmath> and not to be relied upon.

Syntax

cpp
#include <cmath>

// All functions live in namespace std
double r = std::sqrt(2.0);
float  s = std::sqrtf(2.0f);   // C-style suffix form β€” still valid
float  t = std::sqrt(2.0f);    // C++11: preferred float overload

Since C++11 every function is overloaded for float, double, and long double. When an integer argument is passed the result type is double:

cpp
double x = std::sqrt(4);    // C++11: int promoted to double β†’ 2.0

Examples

Geometry: distance and angle

cpp
#include <cmath>
#include <numbers>  // C++20: std::numbers::pi
#include <print>    // C++23: std::println

struct Vec2 { double x, y; };

double magnitude(Vec2 v) {
    return std::hypot(v.x, v.y);  // avoids intermediate overflow
}

double angle_deg(Vec2 v) {
    double rad = std::atan2(v.y, v.x);
    return rad * (180.0 / std::numbers::pi);  // C++20
}

int main() {
    Vec2 v{3.0, 4.0};
    std::println("magnitude: {}", magnitude(v));   // 5.0
    std::println("angle: {}Β°", angle_deg(v));       // 53.13...
}

std::hypot computes √(x²+y²) without the overflow risk of writing std::sqrt(x*x + y*y). Since C++17, a three-argument form std::hypot(x, y, z) computes the 3-D Euclidean norm.

Floating-point classification

cpp
#include <cmath>
#include <limits>

bool safe_log(double x, double& result) {
    if (!std::isfinite(x) || x <= 0.0)
        return false;
    result = std::log(x);
    return true;
}

void inspect(double v) {
    switch (std::fpclassify(v)) {
        case FP_INFINITE:  /* handle inf  */ break;
        case FP_NAN:       /* handle NaN  */ break;
        case FP_SUBNORMAL: /* handle denormal */ break;
        case FP_ZERO:      /* handle zero */ break;
        case FP_NORMAL:    /* ordinary value  */ break;
    }
}

std::isnan, std::isinf, and std::isfinite (C++11 function templates) replace the isnan / isinf macros from C. Prefer the std:: versions; the global-namespace macros may not exist in all translation units.

Rounding modes

cpp
#include <cmath>

// C++11: all rounding variants exist
double v = 2.7;

std::floor(v);      // 2.0  β€” toward -∞
std::ceil(v);       // 3.0  β€” toward +∞
std::trunc(v);      // 2.0  β€” toward zero (C++11)
std::round(v);      // 3.0  β€” nearest, halfway away from zero
std::nearbyint(v);  // 3.0  β€” nearest, respects current rounding mode, no FE_INEXACT
std::rint(v);       // 3.0  β€” nearest, respects current rounding mode, raises FE_INEXACT

std::nearbyint and std::rint differ only in whether they raise the FE_INEXACT floating-point exception. If you need to suppress that exception (e.g., in hot inner loops where <cfenv> error tracking is active), prefer std::nearbyint.

Fused multiply-add

cpp
#include <cmath>

// C++11: std::fma computes (x * y) + z with a single rounding step
double dot(double ax, double bx, double ay, double by) {
    return std::fma(ax, bx, ay * by);
}

std::fma (C++11) is exact to within one ULP when the hardware provides a native FMA instruction. On platforms without native FMA it is emulated but still produces the correct mathematical result. Use it whenever intermediate rounding in x*y + z would be a problem β€” polynomial evaluation being the classic case.

Error handling

cpp
#include <cmath>
#include <cerrno>
#include <cstring>

double safe_sqrt(double x) {
    errno = 0;
    double r = std::sqrt(x);
    if (errno == EDOM)
        throw std::domain_error("sqrt of negative");
    return r;
}

Error reporting from <cmath> is controlled by math_errhandling (defined in <cmath>, not in namespace std). It holds a bitwise OR of:

ConstantMeaning
MATH_ERRNOErrors reported via errno
MATH_ERREXCEPTErrors raised as floating-point exceptions (<cfenv>)

At least one of the two bits is set by any conforming implementation. On most Linux/glibc targets both are set; on MSVC only MATH_ERRNO is. Do not assume a specific combination.

Best Practices

Prefer std::hypot over manual Pythagorean sums. Writing std::sqrt(x*x + y*y) overflows when x or y exceeds √DBL_MAX β‰ˆ 1.3Γ—10¹⁡⁴. std::hypot is required by the standard to avoid spurious overflow and underflow.

Use std::fma for compensated arithmetic. When building polynomial evaluators (Horner's method) or compensated summations, std::fma eliminates the intermediate rounding step and typically maps to a single hardware instruction on x86-64 (VFMADD), ARM (FMADD), and POWER (fmadd).

Classify before computing. Always guard std::log, std::sqrt, std::asin, and similar domain-restricted functions with std::isfinite and range checks on untrusted input. Passing a negative value to std::sqrt sets errno = EDOM and returns NaN β€” it does not throw.

Match argument and return types. Mixing float arguments with a double result variable triggers an implicit widening conversion that silently defeats the purpose of using float for performance. Assign to the same type: float r = std::sqrtf(x) or float r = std::sqrt(x) (C++11 overload).

Do not use using namespace std; to shorten math calls in headers. Importing the entire std namespace in a header drags in hundreds of names and is a well-known source of ODR violations.

Common Pitfalls

std::abs vs std::fabs for floating-point. std::abs with a double argument is declared in <cmath> since C++11. Before C++11, std::abs for floating-point was only guaranteed by including <cstdlib> (which provided the integer version) or <cmath>. With C++11 or later, prefer std::abs with <cmath> included. Including only <cstdlib> and calling std::abs(3.7) silently truncates to integer abs on older compilers.

NaN propagation is asymmetric for min/max. std::fmin(NaN, 1.0) returns 1.0 (NaN is treated as missing data per IEEE 754), whereas std::min(NaN, 1.0) has unspecified behaviour and frequently returns the wrong value. Use std::fmin/std::fmax when one operand may be NaN.

std::pow(base, 2) is not an optimisation. Many compilers do not special-case integer exponents in std::pow; the call is typically slower and less accurate than base * base. Write the multiplication explicitly or use std::fma(base, base, 0.0).

math_errhandling is not in namespace std. Unlike nearly everything else in <cmath>, math_errhandling, MATH_ERRNO, and MATH_ERREXCEPT are macros defined at global scope. Do not write std::math_errhandling.

Integer literals produce double. std::sqrt(2) is valid C++11 (integer argument overload resolves to double), but std::sqrt(2.f) selects the float overload. Ensure literal suffixes match the intended precision.

See Also

  • <numbers> β€” C++20 mathematical constants (std::numbers::pi, std::numbers::e, …)
  • <cfenv> β€” floating-point environment control (rounding mode, exception flags)
  • <complex> β€” complex-number overloads of most <cmath> functions
  • <numeric> β€” std::gcd, std::lcm, std::midpoint, std::lerp (C++17/20)
  • <valarray> β€” element-wise application of math functions to arrays