[fpc-pascal] Why the difference in the rounded results?
James Richters
james.richters at productionautomation.net
Fri Oct 15 20:44:18 CEST 2021
The difference is because of the way floating point math works.. and how rounding works.
Rounding something that ends with 5 is ambiguous, because it could round up, or it could round down...
You can control the behavior of rounding with SetRoundMode();
See https://www.freepascal.org/docs-html/rtl/math/setroundmode.html
It seems that SetRoundMode is defaulting to SetRoundMode(rmNearest) which doesn't resolve ambiguity for things like 22.575000000... because there is no nearest... 22.57 is EXACTLY the same distance away as 22.58... BUT since we are using floating point... there could be a tiny difference between one or the other making SetRoundMode(rmNearest) round one way for 32 bit and another way for 64 bit.
If you want them to always round the same way, you can just set SetRoundMode() to either SetRoundMode(rmUp) or SetRoundMode(rmDown) and that will remove the ambiguity...
Note that rmUp or rmDown or rmNearest only affect result that round off something with a 5
So with rmUP
22.575 will ALWAYS come out 22.58
And with rmDown
22.575 will ALWAYS come out 22.57
The reason Delphi is showing 2.25800000000000E+0001
And FPC 64 bit is showing 2.2579999999999998E+001
Is because delphi is not showing all the floating point digits... if you do
Writeln(SimpleRoundTo(d1*d2):0:14); with FPC you get
22.58000000000000 because now you are only showing 14 digits after the decimal point like Delphi , not 16 digits like FPC
Note that floating point math with double precision, it's impossible to truly store the number 22.58,
It's either 22.5799999999999999999 on win 32 or 22.579999999999998 on 64bit there is no exact 22.580000000000000000000000000000000000000000..... you have to be one float value or the other. So it doesn't make sense to round a floating point number then try to display more decimal points than you rounded it to, if you are rounding to 2 decimal places than just to a writeln that shows 2 decimal places like Writeln(RoundTo(d1*d2,-2):0:2); and see 22.57 otherwise you will always be seeing floating point weirdness.
There is a difference between the way 64bit stores 22.575, 22.570 and 22.580
If you do
Writeln(22.575:0:20);
Writeln(22.57:0:20);
Writeln(22.58:0:20);
On a 32bit, you get:
22.57500000000000000070
22.56999999999999999970
22.57999999999999999990
On 64bit you get:
22.57499999999999900000
22.57000000000000000000
22.57999999999999800000
Yes, it's true, Win32 has more precision than Win64 I did not get them backwards.. see:
https://wiki.freepascal.org/Variables_and_Data_Types
Where it states:
Note that for Windows 64 bits and non-Intel targets Extended is an alias for Double. So I don't use Win64, I only use 32 bit so I can get the precision.
So when using SetRoundMode(rmNearest) which is the default to decide whether to round 22.575 up or down it's very slightly in nearest to 22.58 with 64 bit and very slightly nearest to 22.57 with 32 bit
James
-----Original Message-----
From: fpc-pascal <fpc-pascal-bounces at lists.freepascal.org> On Behalf Of Gabor Boros via fpc-pascal
Sent: Friday, October 15, 2021 5:50 AM
To: fpc-pascal at lists.freepascal.org
Cc: Gabor Boros <mlnglsts at bgss.hu>
Subject: [fpc-pascal] Why the difference in the rounded results?
Hi All,
I got different results with 32bit vs. 64bit, 3.2.2 vs. 3.3.1, FPC vs.
Delphi. Why?
var
d1,d2:Double;
begin
d1:=20.5;
d2:=1.05;
Writeln(RoundTo(d1*d2,-2));
Writeln(SimpleRoundTo(d1*d2));
d1:=28.9;
Writeln;
Writeln(RoundTo(d1*d2,-2));
Writeln(SimpleRoundTo(d1*d2));
d1:=21.5;
Writeln;
Writeln(RoundTo(d1*d2,-2));
Writeln(SimpleRoundTo(d1*d2));
Readln;
end.
- FPC 3.2.2 Win32
2.1530000000000001E+001
2.1530000000000001E+001
3.0340000000000000E+001
3.0340000000000000E+001
2.2570000000000000E+001
2.2570000000000000E+001
- FPC 3.2.2 Win64
2.1520000000000003E+001
2.1530000000000001E+001
3.0340000000000007E+001
3.0350000000000001E+001
2.2570000000000004E+001
2.2579999999999998E+001
- FPC 3.3.1 Win32
2.1530000000000001E+001
2.1530000000000001E+001
3.0340000000000000E+001
3.0340000000000000E+001
2.2570000000000000E+001
2.2570000000000000E+001
- FPC 3.3.1 Win64
2.1520000000000003E+001
2.1530000000000001E+001
3.0340000000000007E+001
3.0350000000000001E+001
2.2570000000000004E+001
2.2579999999999998E+001
- Delphi 10.4.2 Win32
2.15300000000000E+0001
2.15300000000000E+0001
3.03400000000000E+0001
3.03400000000000E+0001
2.25800000000000E+0001
2.25800000000000E+0001
- Delphi 10.4.2 Win64
2.15200000000000E+0001
2.15300000000000E+0001
3.03400000000000E+0001
3.03500000000000E+0001
2.25800000000000E+0001
2.25800000000000E+0001
Gabor
_______________________________________________
fpc-pascal maillist - fpc-pascal at lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
More information about the fpc-pascal
mailing list