BartC said:
What implementation are you using?
This program:
#include <stdio.h>
int main(void)
{
printf("%f\n", 1e40); [...]
return 0;
}
gives me this output:
10000000000000000303786028427003666890752.000000
(That matches the result in my other post; a good sign..)
Oh? You said you got "an impossibly clean result of 1 followed by loads
of zeros"; that doesn't look "impossibly clean" to me.
lcc-win32 and gcc (all on x86-32) both give me:
10000000000000000000000000000000000000000.000000
100000000000000000000000000000000000000000.000000
1000000000000000000000000000000000000000000.000000
10000000000000000000000000000000000000000000.000000
100000000000000010000000000000000000000000000.000000
999999999999999930000000000000000000000000000.000000
....
gcc probably isn't relevant; printf is provided by the runtime library,
not by the compiler. For lcc-win32, apparently both are form the same
source, but gcc will use whatever runtime library is on the system.
gcc with glibc on Linux produces the results I posted. gcc on Cygwin
(which I think uses something called "newlib") produces subtly different
results for some values; the Cygwin results are identical for 1e40,
1e41, and 1e42, but have more trailing zeros before the decimal point
for the other values.
glibc seems to be showing the exact stored value, or something
close to it. The results you're getting seem to be the result of
something doing some rounding somewhere.
Using DMC, I do get the 303 in the middle of 1e40 for example, but the rest
is still zeros:
10000000000000000303000000000000000000000.000000
Odd. Perhaps some compiler switch is needed?
Unless a compiler switch affects the behavior of the runtime library
(which is possible), you're probably stuck with the behavior you're
getting unless you change systems.
I think it's because you start with an integer (of 52/53 bits for example),
then end up multiplying by a power of two, at least for these bigger
numbers.
Right.
Trouble is I don't 'read' hex; that's why I used a separate program to
extract the bits and build the number.
....
Ok, here's some new information. Using Perl's Math::BigInt, I've
converted the results (with the trailing ".000000" ignored) to
hexadecimal. The results I got with glibc are:
0x1d6329f1c35ca500000000000000000000
0x125dfa371a19e7000000000000000000000
0xb7abc627050308000000000000000000000
0x72cb5bd86321e40000000000000000000000
0x47bf19673df53000000000000000000000000
0x2cd76fe086b93c000000000000000000000000
0x1c06a5ec5433c60000000000000000000000000
0x118427b3b4a05c00000000000000000000000000
0xaf298d050e439800000000000000000000000000
0x6d79f82328ea3c000000000000000000000000000
0x446c3b15f992680000000000000000000000000000
showing about 53 significant bits followed by zeros, which makes sense.
The results I got on Cygwin are:
0x1d6329f1c35ca500000000000000000000
0x125dfa371a19e7000000000000000000000
0xb7abc627050308000000000000000000000
0x72cb5bd86321e3fffffffffffffffffffffc
0x47bf19673df53000000000000000000000010
0x2cd76fe086b93c000000000000000000000020
0x1c06a5ec5433c5ffffffffffffffffffffffe90
0x118427b3b4a05c00000000000000000000008800
0xaf298d050e439800000000000000000000055000
0x6d79f82328ea3c0000000000000000000000335c0
0x446c3b15f992680000000000000000000001bb5200
which implies some spurious rounding.
Your output of
100000000000000010000000000000000000000000000.000000
is
0x47bf19673df5303cef26e3f42126110000000
which has 118 significant bits.
I'm not suggesting that the implementations you're using are
non-conforming; I don't think printf is required to print more
significant digits than are really there. The standard says "The
value is rounded to the appropriate number of digits."; there may
be some disagreement among implementers about what this means.
My guess is that
100000000000000010000000000000000000000000000.000000
results from computing a rounded result, and then picking up an
insignificant digit in the conversion to a string. I'd probably
call that a bug, but not in the sense that it's non-conforming.