Those who visit the chat might have seen the question of varkor. I'm posting it here in the hope that I have missed something.
Assume you have a real number
real = 57.295780181884765625;
This number fits exactly into a 32 bit floating point number (known as IEEE-754) as you can verify on this site. However, exporting and importing it again looses information:
ImportString[ExportString[real, "Real32"], "Real32"] // InputForm
(* {57.295780181884766} *)
Additionally, you can check that the precision of real
is about 20
Precision[real]
(* 19.7581 *)
while the re-imported number only has MachinePrecision
which is about 15. Actually, the situation is worse because even if you use "Real64"
, the re-imported number will still have only MachinePrecision
and the loss of information is exactly as large as when using "Real32"
.
I was curious if the exported bytes are wrong or if the the re-import fails. We can store the binary value and re-import it as "Binary"
so that we get the actual bytes. These bytes are then turned into a bit pattern (the Reverse
is due to the byte ordering):
bin = ExportString[real, "Real32"];
digits = Flatten[IntegerDigits[Reverse@ImportString[bin, "Binary"], 2, 8]]
(* {0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,1,1,1,0,1,1,1,0,0,0,0,1} *)
The bits are exactly as given on the site I linked above and we can turn them back into a number by following the calculation of IEEE-754
e = Sum[digits[[9 - i]]*2^i, {i, 0, 7}];
fraction = 1 + Sum[digits[[9 + i]]*2^(-i), {i, 1, 23}];
result = 2^(e - 127)*fraction;
N[result, 30]
(* 57.2957801818847656250000000000 *)
As you can see, the result is exactly what we have used as input.
Question: Why is a "Real32"
or a "Real64"
not imported correctly? You will find that using "Real128"
indeed returns the correct result and a number with an explicit precision. What is happening here?
MachinePrecision
. The ~20 or so precision that you are seeing is an artifact of representing the number as a bigreal. When importing, anything that fits into a native double will be converted to one. "Real128" of course, can only return a bigreal. $\endgroup$