Re: [fpc-pascal] Floating point question

2024-02-19 Thread Sven Barth via fpc-pascal
James Richters via fpc-pascal  schrieb am
Di., 20. Feb. 2024, 04:42:

> I don't know why it would be different in Windows than on Linux.


If you're using Win64, then the answer is simple: x86_64-win64 unlike any
other x86 target does not support Extended, so neither the compiler nor the
code in runtime will ever calculate anything with that precision.

Regards,
Sven
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-19 Thread James Richters via fpc-pascal
>I would not put too much trust in Windows calculator, since there you have
no control over the precision at all.
The actual CORRECT answer according to
https://www.wolframalpha.com/input?i=1%2F3.5 Is 
0.285714 Repeating forever

Which is what I get on windows only when using Variables.
   Var_Ans1 =  2.85714285714285714282E-0001
Which as you can see the .285714 repeats exactly 3 times with two more
correct digits, for a total of 20 correct digits before we run out of
precision. 

>It seems to be a windows-specific problem. Here is the result of your
program when executed on Linux:
>  Const_Ans1 =  2.85714298486709594727E-0001
>Var_Ans1 =  2.85714298486709594727E-0001

>As you can see, the result is identical.
Great, Linux is consistently giving you the wrong answer, and I notice it's
the same wrong I answer I get when I use constants.

I don't know why it would be different in Windows than on Linux. 
I am curious what you get in Linux for:
A_const = (2/7);   // should be 0.285714 Repeating forever also
Or 
B_const = (2/7)-(1/3.5);  //should always be 0;

Just for fun I ran it on Turbo Pascal 7.0 for DOS and got:
 Const_Ans1 =  2.85714285714286E-0001
 Var_Ans1 =  2.85714285714286E-0001

I also noticed that re-casting constants is not allowed by Turbo Pascal 7.0,
so I removed the unnecessary re-casting so it would compile, but I did get
the expected answer even without re-casting it... as I expected I should. 
The fact that Turbo Pascal gives be the correct answer to 14 digits even
though in Turbo Pascal I also divided a byte by a single shows that I should
expect my pascal programs to provide THIS correct answer, 0.285714 repeating
until you run out of precision,  not something else. And it shows that a
byte divided by a single is in fact able to be an extended... it also proves
that in Pascal the result of a byte divided by a single is NOT limited to
single precision. 

2.85714298486709594727E-0001 makes no sense to me at all, It's like it did
the calculation in Single precision, then stored it in an extended, but if I
wanted to work in single precision, I would not have set my variable to
extended.

There is some flawed logic somewhere that says if you do math with a single,
the result is a single, but this is simply not correct, you can divide a
byte by a byte and get an extended, and you can divide a single by a single
and get an extended, Pascal has ALWAYS worked that way.
Forcing the result of an equation to be a single because one term is a
single is just not right. 

James

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


Re: [fpc-pascal] Floating point question

2024-02-19 Thread Michael Van Canneyt via fpc-pascal




On Sun, 18 Feb 2024, James Richters via fpc-pascal wrote:


And if you have set the precision, then the calculation will be identical to 
the calculation when you use a variable of the same type (if not, it's indeed a 
bug).


This is what I have been trying to point out.  Math with identical casting with 
variables and constants are not the same.
Maybe if I try with a simpler example:

program Const_Vs_Var;

Const
  A_const = Byte(1);
  B_const = Single(3.5);
Var
  A_Var : Byte;
  B_Var : Single;
  Const_Ans1, Var_Ans1 : Extended;

Begin
  A_Var := A_Const;
  B_Var := B_Const;

  Const_Ans1 := Extended(Byte(A_Const)/Single(B_Const));
  Var_Ans1   := Extended(Byte(A_Var)/Single(B_Var));

  WRITELN ( ' Const_Ans1 = ', Const_Ans1);
  WRITELN ( '   Var_Ans1 = ',   Var_Ans1);
End.

Const_Ans1 =  2.85714298486709594727E-0001
  Var_Ans1 =  2.85714285714285714282E-0001

Windows 10 Calculator shows the answer to be
0.28571428571428571428571428571429  Which matches up with the way variables 
have done this math, not the way constants have done it.


I would not put too much trust in Windows calculator, since there you have
no control over the precision at all.

It seems to be a windows-specific problem. Here is the result of your
program when executed on Linux:

 Const_Ans1 =  2.85714298486709594727E-0001
   Var_Ans1 =  2.85714298486709594727E-0001

As you can see, the result is identifical.

As for the explanation, I will have to leave that to the compiler developers.

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


Re: [fpc-pascal] Floating point question

2024-02-19 Thread James Richters via fpc-pascal
>And if you have set the precision, then the calculation will be identical to 
>the calculation when you use a variable of the same type (if not, it's indeed 
>a bug).
 
This is what I have been trying to point out.  Math with identical casting with 
variables and constants are not the same.
Maybe if I try with a simpler example:
 
program Const_Vs_Var;
 
Const
   A_const = Byte(1);
   B_const = Single(3.5);
Var
   A_Var : Byte;
   B_Var : Single;
   Const_Ans1, Var_Ans1 : Extended;
 
Begin
   A_Var := A_Const;
   B_Var := B_Const;
 
   Const_Ans1 := Extended(Byte(A_Const)/Single(B_Const));
   Var_Ans1   := Extended(Byte(A_Var)/Single(B_Var));
 
   WRITELN ( ' Const_Ans1 = ', Const_Ans1);
   WRITELN ( '   Var_Ans1 = ',   Var_Ans1);
End.
 
Const_Ans1 =  2.85714298486709594727E-0001
   Var_Ans1 =  2.85714285714285714282E-0001
 
Windows 10 Calculator shows the answer to be
0.28571428571428571428571428571429  Which matches up with the way variables 
have done this math, not the way constants have done it.
 
I am explicitly casting everything I possibly can.
 
Without the :20:20 you can see that the result of each of these is in fact 
extended, but they are VERY different numbers, even though my casting is 
IDENTICAL , and I can’t make it any more the same, the results are very 
different.  Math with Variables allows the result of a low precision entity, in 
this case a Byte, divided by a low precision entity, in this case a Single, to 
be calculated and stored in an Extended, Math with Constants does not allow 
this possibility, and this is where all the confusion is coming from.Two 
identical pieces of code not producing the same results.
 
Math with Constants is NOT the same as Math with Variables, and if this one 
thing was fixed, then all the other problems go away.
I am doing:  
   Const_Ans1 := Extended(Byte(A_Const)/Single(B_Const));
   Var_Ans1   := Extended(Byte(A_Var)/Single(B_Var));
 
Just to make a point, but the code:
 
   Const_Ans1 := A_Const/B_Const;
   Var_Ans1   := A_Var/B_Var;
 
Should also produce identical results without re-casting, because A_Const  and 
A_Var are both defined to be a Byte, and B_Const and B_Var are both defined to 
be a Single, and Const_Ans1 and Var_Ans1 are both defined to be Extended. 
 
Why are the result different?  
 
As I tried to explain before, if I force all constants to be Extended:
Const_Ans1 := Extended(Extended(A_Const)/Extended(B_Const));
 
Then I do get the correct results, but this should not be needed, and this 
casting is wrong,  because a byte divided by a single should be able to be 
extended without first storing them in extended entities, the same as it is 
with variables. 
 
With variables I do not need to re-cast every single term in an expression as 
Extended to get an Extended answer. 
With constants this is the ONLY way I can get an extended answer. 
 
Before the changes to 2.2, all constants WERE at highest precision, so the math 
involving constants never had to bother with considering that a low precision 
number divided by a low precision number could end up as an extended, because 
there were no low precision constants at all.But now there are, and that’s 
really fine, because we often have low precision variables, and that’s fine, 
but the math needs to be done the same way whether with constants or variables 
to produce identical results so now math with constants also has to take into 
consideration that math with low precision entities can and often does result 
in a high precision answer. 
 
To demonstrate that a low precision entity divided by a low precision entity 
should always be able to be an Extended, use this example my constants as BYTES 
so there can be no lower precision:
 
program Const_Vs_Var;
 
Const
   A_const = Byte(2);
   B_const = Byte(7);
Var
   A_Var : Byte;
   B_Var : Byte;
   Const_Ans1, Const_Ans2, Var_Ans1 : Extended;
 
Begin
   A_Var := Byte(A_Const);
   B_Var := Byte(B_Const);
 
   Const_Ans1 := A_Const/B_Const;
   Var_Ans1   := A_Var/B_Var;
 
   WRITELN ( ' Const_Ans1 = ', Const_Ans1);
   WRITELN ( '   Var_Ans1 = ',   Var_Ans1);
End.
 
Const_Ans1 =  2.85714285714285714282E-0001
   Var_Ans1 =  2.85714285714285714282E-0001
 
Now as you can see math with constants is EXCATLY the same as math with 
variables again, and I did not need to do any ridiculous casting to get the 
correct answer. 
 
I hope this makes sense.  I know exactly what is happening, but I don’t know 
why and I don’t know how to explain it other than to give these examples.
 
1/3.5 == 2/7
 
What should this program produce?
 
program Const_Vs_Var;
 
Const
   A_const = (2/7)-(1/3.5);
Begin
   WRITELN ( ' A_Const = ', A_Const);
End.
 
 
How can this possibly be right?
A_Const = -1.27724238804447203649E-0008
 
 
 
James
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal