float.h
float.h tells you the hard limits of floating-point arithmetic on the platform you are compiling for: how many decimal digits double can represent reliably, the largest and smallest values, and machine epsilon. You reach for it when writing numerical code that needs to be correct across platforms rather than just on your development machine.
The most useful macros for double:
| Macro | Typical value | Meaning |
DBL_EPSILON | ~2.22e-16 | Smallest value where 1.0 + epsilon != 1.0 |
DBL_MAX | ~1.80e+308 | Largest finite double |
DBL_MIN | ~2.22e-308 | Smallest normalised positive double |
DBL_DIG | 15 | Decimal digits of precision |
DBL_MANT_DIG | 53 | Binary mantissa digits |
Equivalent macros exist for float (FLT_*) and long double (LDBL_*). FLT_RADIX is the exponent base — 2 on every modern platform.
DBL_EPSILON is the constant you need for floating-point comparisons. Instead of a == b, use a relative comparison:
#include <float.h> #include <math.h> int nearly_equal(double a, double b) { return fabs(a - b) <= DBL_EPSILON * fmax(fabs(a), fabs(b)); }
The right threshold depends on how many operations accumulated error, but DBL_EPSILON is the floor: no two distinct doubles within this range can be reliably distinguished.
Practice
// compile: gcc -o floatlimits floatlimits.c -lm // run: ./floatlimits // description: print floating-point limits and demonstrate machine epsilon behaviour #include <float.h> #include <math.h> #include <stdio.h> int main(void) { printf("DBL_EPSILON = %.2e\n", DBL_EPSILON); printf("1.0 + DBL_EPSILON != 1.0: %s\n", (1.0 + DBL_EPSILON != 1.0) ? "true" : "false"); printf("1.0 + DBL_EPSILON/2 != 1.0: %s\n", (1.0 + DBL_EPSILON/2.0 != 1.0) ? "true" : "false"); printf("DBL_MAX = %.6e\n", DBL_MAX); printf("DBL_MAX*2 = %g\n", DBL_MAX * 2.0); // infinity printf("DBL_DIG = %d decimal digits\n", DBL_DIG); return 0; }
The DBL_EPSILON/2 line is the key insight: add half an epsilon to 1.0 and it disappears, because it falls below the resolution of the mantissa at that scale. DBL_MAX * 2.0 prints inf, showing where the exponent range ends. Run this on a 32-bit and a 64-bit machine and the double values will be identical (IEEE 754 is the same), but LDBL_EPSILON may differ because long double is 80-bit on x86 and 64-bit on some other architectures.
