Ernst-Ludwig Bohnen wrote:
On Sat, 24 Mar 2001, Russ Whitaker wrote:
On Sat, 24 Mar 2001, f.couperin wrote:
Hello,
I don't know if it's really a bug but the result is really surprising. A LongReal variable (of simple integer value) is written into a text file, and when I read this value back : it isn't exactly the same.
[..]
Program LRealBug; Var A,B : LongReal; TextFile : Text; Begin Assign(TextFile,'tmp'); Rewrite(TextFile); A := 103; Writeln(TextFile,A); Close(TextFile); Reset(TextFile); Readln(TextFile,B); Close(TextFile); Erase (TextFile); If A <> B Then Writeln('Failed') Else Writeln('OK'); End.
The problem is "A <> B": adding two lines to program writeln('A= ', A); writeln('B= ', B); and I got:
A= 1.030000000000000e+02 B= 1.030000000000000e+02 Failed
Hopes this helps Russ
Why should this help? If A=B the answer should be 'OK'. But there may be the long time known problem with comparing real numbers nearly zero difference, equality comparison of real's is never reliable.
[...]
After thinking 3 more minutes about this problem, the conversion between binary and decimal presentation may produce low order bit differences of A and B ;-)). Other types (real etc) may veil the latent problem.
Exactly. If you add the statements:
WriteLn (A - 103); WriteLn (B - 103);
you'll see:
0.000000000000000e+00 -6.938893903907228e-18
So, why is B slighly inaccurate? Well, if you look at the file, it contains the text:
1.030000000000000e+02
And that's exactly what ReadLn sees. I.e., first the number 1.03 which cannot be represented exactly since floating point numbers (at least IEEE and most other popular formats) are binary, not decimal, and 1.03 in binary is periodic.
Afterwards, it finds `e+02' and multiplies the result by 100 which can be done exactly, but the error was already made.
So, why does it happen only with LongReal?
Normally, a floating point system uses a few extra digits to avoid such roundoff errors. But (at least on Intel compatibles), this only holds for the regular types (ShortReal aka Single and Real aka Double). LongReal (aka Extended), however, is the full precision used internally, so there are no extra digits, and every roundoff error really shows. I think it was originally meant as an internal type, only to be used to store intermediate results, and not as a type to be used at the "user level". So if you do that, you're basically on your own. (I don't know if there are processors that provide a LongReal type bigger than Double which does have some extra digits internally.)
BTW, if you do
WriteLn (TextFile, A:0:30);
or something like that, A will be written as 103.000000000000000000000000000000, and B will be read back precisely, but that's no general help against roundoff errors...
Frank