Table of Contents

math.h

math.h is the standard mathematical function library for floating-point arithmetic. It covers trigonometry, exponentiation, logarithms, rounding, and a handful of utility functions. Every function operates on double by default; append f for float (sinf, sqrtf) or l for long double (sinl). You have to link with -lm on most systems.

#include <math.h>
// compile with: -lm
 
double y = sqrt(2.0);       // 1.4142...
double s = sin(M_PI / 6);   // 0.5  (M_PI is a common extension, not strictly standard)
double e = exp(1.0);        // e ≈ 2.71828
double l = log(M_E);        // 1.0  (natural log)
double p = pow(2.0, 10.0);  // 1024.0
double a = fabs(-3.5);      // 3.5
double r = floor(3.7);      // 3.0
double c = ceil(3.2);       // 4.0
double t = round(3.5);      // 4.0  (half away from zero)

C99 added several functions that are more numerically stable than the naive equivalents:

hypot(3.0, 4.0)    // sqrt(3²+4²) = 5.0 without intermediate overflow
cbrt(27.0)         // cube root = 3.0
log2(1024.0)       // 10.0
log1p(1e-15)       // log(1+x), accurate for small x
expm1(1e-15)       // exp(x)-1, accurate for small x

Domain errors (e.g. sqrt(-1)) return NaN and set errno to EDOM. Range errors (e.g. exp(1e308)) return HUGE_VAL and set errno to ERANGE. The C99 macros isnan, isinf, and isfinite test the class of a result without triggering the quirks of comparing NaN with ==.

Practice

// compile: gcc -O2 -o mathdemo mathdemo.c -lm
// run: ./mathdemo
// description: Pythagorean triple, domain error, and log1p accuracy demo
 
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
 
int main(void) {
    // basic: 3-4-5 right triangle
    printf("hypot(3,4) = %.1f\n", hypot(3.0, 4.0));
 
    // domain error: sqrt of negative number
    errno = 0;
    double bad = sqrt(-1.0);
    printf("sqrt(-1) = %g  isnan=%d  errno=%s\n",
           bad, isnan(bad), strerror(errno));
 
    // accuracy: log1p vs log(1+x) for very small x
    double x = 1e-15;
    printf("log(1+x)  = %.20f\n", log(1.0 + x));   // loses precision
    printf("log1p(x)  = %.20f\n", log1p(x));        // accurate
    return 0;
}

The log1p vs log(1+x) comparison is instructive: for very small x, 1.0 + x rounds to exactly 1.0 in double precision, so log(1.0 + x) returns 0. log1p(x) is implemented to avoid this cancellation and returns the correct small value. This is the kind of subtlety that <math.h> addresses if you use the right function.