To simplify the problem further:

the addition of 12 /24.0 and the subtraction of 0.5 should be removed, IMO,
because both can be done with floats without loss of precision (0.5 can be represented exactly in float).

So the problem can be reproduced IMO with this small Pascal program:

program TESTDBL1 ;

var TT : REAL ;

begin (* HAUPTPROGRAMM *)
  TT := 8427 + 33 / 1440.0 ;
  WRITELN ( 'tt=' , TT : 20 : 20 ) ;
end (* HAUPTPROGRAMM *) .

With my compiler, REAL is always DOUBLE, and the computation is carried out by a P-Code interpreter
(or call it just-in-time compiler - much like Java), which is written in C.

The result is:

tt=8427.02291666666678790000

and it is the same, no matter if I use this simplified computation or the original

tt := (8427 - 0.5) + (12 / 24.0) + (33 / 1440.0);

My value is between the two other values:

tt=8427.02291666666680000000
tt=8427.02291666666678790000
ee=8427.02291666666666625000

The problem now is:

the printout of my value suggest an accuracy which in fact is not there, because with double, you can trust only the first 16 decimal digits ... after that, all is speculative a.k.a. wrong. That's why FPC IMO rounds at this
place, prints the 8, and then only zeroes.

The extended format internally has more hex digits and therefore can reliably show more decimal digits.
But the last two are wrong, too (the exact value is 66666... period).

HTH,
kind regards

Bernd



Am 27.01.2024 um 22:53 schrieb Bart via fpc-pascal:
On Sat, Jan 27, 2024 at 6:23 PM Thomas Kurz via fpc-pascal
<fpc-pascal@lists.freepascal.org>  wrote:

Hmmm... I don't think I can understand that. If the precision of "double" were 
that bad, it wouldn't be possible to store dates up to a precision of milliseconds in a 
TDateTime. I have a discrepancy of 40 seconds here.
Consider the following simplified program:
====
var
   tt: double;
   ee: extended;

begin
   tt := (8427 - Double(0.5)) + (12/ Double(24.0)) +
(33/Double(1440.0)) + (0/Double(86400.0));
   ee := (8427 - Extended(0.5)) + (12/ Extended(24.0)) +
(33/Extended(1440.0)) + (0/Extended(86400.0));
   writeln('tt=',tt:20:20);
   writeln('ee=',ee:20:20);
end.
===

Now see what it outputs:

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
...

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
tt=8427.02291666666680000000
ee=8427.02291666666666625000

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc -Px86_64 test.pas
Free Pascal Compiler version 3.2.2 [2021/05/15] for x86_64
..

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
tt=8427.02291666666680000000
ee=8427.02291666666680000000

On Win64 both values are the same, because there Extended = Double.
On Win32 the Extended version is a bit closer to the exact solution:
8427 - 1/2 + 1/2 + 33/1440 = 8427 + 11/480

Simple as that.

Bart
_______________________________________________
fpc-pascal maillist  -fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to