# 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. ```c #include // 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: ```c 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 ```c // compile: gcc -O2 -o mathdemo mathdemo.c -lm // run: ./mathdemo // description: Pythagorean triple, domain error, and log1p accuracy demo #include #include #include #include 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 `` addresses if you use the right function.