I'm currently writing a compiler for my own language in D, and one of the
things I'm implementing at the moment is the processing of floating-point
literals. My primary reference is William Clinger's "How to read floating point
numbers accurately," which is available here:
ftp://ftp.ccs.neu.edu/pub/people/will/howtoread.pdf
Clinger describes a method for guaranteeing the selection of the binary
floating-point number most closely approximating the number input in decimal
(or any other base). So far so good, but along the way I've had occasion to
consider what D itself is doing, and I have a couple of questions:
1. Does D guarantee the closest approximation for decimal floating-point
literals? I ask mainly because for unit testing it would be convenient to be
able to write
expect( 0.001 == nearestDouble( 1, -3, 10 ) );
as opposed to manually checking the mantissa and exponent. :-)
2. Minimum exponent. In D, double.min_exp is equal to -1021. However, the
Wikipedia article on IEEE754-2008 and appendix D in Sun's Numerical Computation
Guide ("What Every Computer Scientist Should Know About Floating-Point
Arithmetic", http://docs.sun.com/source/806-3568/ncg_goldberg.html) list Emin
for the IEEE754 double format as -1022. Is this an error?
As expected under the standard, D has no trouble producing a normalized double
with exponent less than -1021:
DoubleRep dr;
dr.value = 0x1p-1022;
writefln("f = %d, e = %d", dr.fraction, dr.exponent);
This prints "f = 0, e = 1", which corresponds to a mantissa of 1.0 and an
exponent of -1022, as expected. If you try 0x1p-1023, you get a denormal, also
as expected, with an exponent field of 0. Subtract DoubleRep.bias and you get
-1023, which according to the standard must be Emin - 1. So why isn't
double.min_exp equal to -1022?