float, double and long double
The logger stores each reading in tenths, but the daily average rarely lands on a neat tenth: 644 tenths over 3 readings is 21.4666… degrees. For values with fractions, C has three floating-point types. They are fast and useful, and they are all approximations.
The rule
Use double by default; floats approximate, so never test them with ==.
| Type | Typical size | Typical precision | Literal |
|---|---|---|---|
float |
32 bits | about 6–7 significant digits | 21.5f |
double |
64 bits | about 15–16 significant digits | 21.5 |
long double |
64 to 128 bits | at least as precise as double |
21.5L |
On almost every machine today, float and double follow the IEEE 754 standard. long double varies most: it is an 80-bit extended format with GCC on x86 Linux, but the same as double with Microsoft's compiler.
Key facts:
- An unsuffixed literal like
21.5is adouble. Addfto get afloat. printfuses%ffor bothfloatanddouble, because afloatargument is promoted todouble.scanfdoes not promote: it needs%ffor afloatand%lffor adouble. Forlong double, both use%Lf.- Most decimal fractions, such as 0.1 and 21.3, have no exact binary form. The stored value is the nearest one available, so small errors creep in and add up.
double avg = 644 / 3.0; /* 214.666..., in tenths */
printf("%.2f\n", avg / 10.0); /* prints 21.47 */float saves memory, which matters when you store thousands of values on a small board, but it is not "simpler" or more accurate. Reach for it deliberately.
The shortcut
Three habits: default to double, write f only on purpose, compare with a tolerance. Instead of a == b, ask "are they close enough?" using fabs from <math.h>:
#include <math.h>
if (fabs(avg - 21.3) < 0.001) { /* close enough to 21.3 */ }The code
double t = 0.0;thent += 0.1;ten times in a loop.
Drills
Answer fast — trust the rule.
What is the type of the literal 18.5?
Which scanf specifier reads a value into a double?
On a typical IEEE 754 machine, what is the value of 0.1 + 0.2 == 0.3?
What does the standard guarantee about long double?
Remember
- Use
doubleby default; floating-point values are approximations. - Shortcut:
fsuffix only on purpose, and compare withfabs(a - b) < tolerance, never==. - Trap:
printfuses%ffor both, butscanfneeds%lffor adouble.
