My program had a bug which was traced to two double precision floats being deemed not equal,
while they "should" have been equal.
You should never compare floats exactly (i.e. with
= or
<>)
unless you can prove that the problem at hand side-steps precision issues.
Apparently, the number 1.9000000000000000 does not exist as a single, double or extended floating point type.
1.9 is indeed
not representable as a
binary IEEE-754 float of any precision.
Similiary to how integers are stored as a sum of powers of 2 (with non-negative exponents, e.g.
9 = %1001 = 1·2³ +
0·2² +
0·2¹ +
1·2⁰), floating-point numbers are made up of a sign, a scaling factor (a binary integer) and a fractional part, which (crucially) is a
binary fraction as opposed to a decimal fraction. Such fractions are also stored as a sum of powers of two, but with
negative exponents only (plus an implicit 1 in most cases). Examples would be
1.5 = 1 + 2⁻¹ or
1.375 = 1 + 2⁻² + 2⁻³.
This means that any given rational number can generally be represented exactly only if that number can be written as a fraction with a denominator that is a power of 2; in your case,
1.9 = 19/10, and since 19 is a prime number, the fraction is irreducible and as such can't be expressed with a power-of-2 denominator. This is analogous to fractions like
1/3 not having a finite decimal representation. Note that precision also plays into this - large denominators simply require more storage bits.
Another implication of the anatomy of floating-point numbers is that they are distributed
exponentially (not uniformly) along the real number line; there are about as many floats between -1 and +1 as there are in the remaining space between negative and positive infinity. In other words, the "
step size" between consecutive floats grows along with their value - for example (applicable only for 32-bit
Single), between
8388608 (2^23) and
16777216 (2^24), only integers are representable (step size 1.0), while between
16777216 and
33554432 (2^25), only even integers are exact (step size 2.0).