# Comparing floating point numbers

suggest changeFloating point types (`float`

, `double`

and `long double`

) cannot precisely represent some numbers because they have finite precision and represent the values in a binary format. Just like we have repeating decimals in base 10 for fractions such as 1/3, there are fractions that cannot be represented finitely in binary too (such as 1/3, but also, more importantly, 1/10). Do not directly compare floating point values; use a delta instead.

#include <float.h> // for DBL_EPSILON and FLT_EPSILON #include <math.h> // for fabs() int main(void) { double a = 0.1; // imprecise: (binary) 0.000110... // may be false or true if (a + a + a + a + a + a + a + a + a + a == 1.0) { printf("10 * 0.1 is indeed 1.0. This is not guaranteed in the general case.\n"); } // Using a small delta value. if (fabs(a + a + a + a + a + a + a + a + a + a - 1.0) < 0.000001) { // C99 5.2.4.2.2p8 guarantees at least 10 decimal digits // of precision for the double type. printf("10 * 0.1 is almost 1.0.\n"); } return 0; }

Another example:

gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition rd11.c -o rd11 -L./lib -lsoq #include <stdio.h> #include <math.h> static inline double rel_diff(double a, double b) { return fabs(a - b) / fmax(fabs(a), fabs(b)); } int main(void) { double d1 = 3.14159265358979; double d2 = 355.0 / 113.0; double epsilon = 1.0; for (int i = 0; i < 10; i++) { if (rel_diff(d1, d2) < epsilon) printf("%d:%.10f <=> %.10f within tolerance %.10f (rel diff %.4E)\n", i, d1, d2, epsilon, rel_diff(d1, d2)); else printf("%d:%.10f <=> %.10f out of tolerance %.10f (rel diff %.4E)\n", i, d1, d2, epsilon, rel_diff(d1, d2)); epsilon /= 10.0; } return 0; }

Output:

0:3.1415926536 <=> 3.1415929204 within tolerance 1.0000000000 (rel diff 8.4914E-08) 1:3.1415926536 <=> 3.1415929204 within tolerance 0.1000000000 (rel diff 8.4914E-08) 2:3.1415926536 <=> 3.1415929204 within tolerance 0.0100000000 (rel diff 8.4914E-08) 3:3.1415926536 <=> 3.1415929204 within tolerance 0.0010000000 (rel diff 8.4914E-08) 4:3.1415926536 <=> 3.1415929204 within tolerance 0.0001000000 (rel diff 8.4914E-08) 5:3.1415926536 <=> 3.1415929204 within tolerance 0.0000100000 (rel diff 8.4914E-08) 6:3.1415926536 <=> 3.1415929204 within tolerance 0.0000010000 (rel diff 8.4914E-08) 7:3.1415926536 <=> 3.1415929204 within tolerance 0.0000001000 (rel diff 8.4914E-08) 8:3.1415926536 <=> 3.1415929204 out of tolerance 0.0000000100 (rel diff 8.4914E-08) 9:3.1415926536 <=> 3.1415929204 out of tolerance 0.0000000010 (rel diff 8.4914E-08)

Found a mistake? Have a question or improvement idea?
Let me know.

Table Of Contents