Hi,
In addition to the expert advice already given, it might help to realise how floating point numbers are stored (very basically).
They are like a number in scientific format, say -1.23e-4 say, except in binary (very basically speaking). So there is 4 parts: the sign of the mantissa; the mantissa (1.23) ; the exponent sign; and the exponent.
The mantissa is stored as a binary fraction less than 1 with the first digit being 1 (the exponent is adjusted to suit). So the mantissa of 7.5 is stored as 11 because 0.5 + 0.25 is 0.75 and 1/2 + 1/4 is 0.11 in binary.
So this has a bunch of consequences, one of which is not every real number can be represented exactly:
1 2 3 4 5 6 7 8 9 10
|
float a = 0.1; // a = 0.0999997 maybe
if (a == 0.1){} // almost certainly false
if (10.0 * a == 1.0){} // almost certainly false
const float PRECISION 1e-6;
const float MyNum = 10 * a;
if (std::abs (1.0 - MyNum) < PRECISION ){} // should be true MyNum == 1.0 to 6dp
| |
Changing the type to double doesn't help - now we 15 or 16 significant figures instead of 6 or 7.
The precision of floats is a problem: if one has a number larger than 1 or 10 million depending on whether your system has 6 or 7 significant figures for floats; then decimal fractions are no longer represented. That is, we can no longer represent 1000000.1
So it is a good idea to always use double rather than float, unless you are using some graphics library that requires them, say.
double
is usually good enough for most people, but there are extended precision types in libraries such as boost and others. For example Astrophysicists use light years instead of metres for units.
long double
only provides an extra 2 significant figures, but has larger exponents.
I read somewhere that exact decimal are coming / proposed in C++17.