A Scheme user asks:
Why is (* .1 7) printed as
0.7000000000000001, rather than as 0.7?
Floating-point numbers in most Scheme implementations are
[IEEE] double precision consisting of a 53 bit
mantissa multiplied by a power of two. 0.1 cannot be
exactly represented in this format; the closest double precision number
is:
(/ #x1999999999999a (expt 2 56))
(- .1 (/ #x19999999999999 (expt 2 56))) ==> 13.877787807814456e-18
(- .1 (/ #x1999999999999a (expt 2 56))) ==> 0.0
(- .1 (/ #x1999999999999b (expt 2 56))) ==> -13.877787807814456e-18
Multiplying (/ #x1999999999999a (expt 2 56)) by 7 yields:
(/ #xb3333333333336 (expt 2 56))
The closest (normalized) IEEE double is:
(/ #x16666666666667 (expt 2 53))
This number is too large to be correctly written as 0.7:
(- .7 (/ #x16666666666667 (expt 2 53))) ==> -111.02230246251565e-18
(- .7 (/ #x16666666666666 (expt 2 53))) ==> 0.0
(- .7 (/ #x16666666666665 (expt 2 53))) ==> 111.02230246251565e-18
(- .7 (* 7 .1)) ==> -111.02230246251565e-18
The last calculation makes plain that this is not an issue of number
syntax, but of numerical conditioning. (* .1 7) is not
printed as 0.7 because it is not equal to
0.7.
Conclusions:
- When you want compactly printed floating-point numbers, use
printf
or format.
- Treat every arithmetic operation as potentially reducing the
precision of floating-point operands.
References:
We are guests and not members of the MIT Computer Science and Artificial Intelligence Laboratory.
Our actions and comments do not reflect in any way on MIT.
|
| Radey Shouman and Aubrey Jaffer
| Go Figure!
|