Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2021-10

Why the difference in the rounded results?

6 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Gabor Boros

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

Reply by email

Guillermo
to Gabor Boros

Hi,

Silly question: Were all compiled an executed in the same computer and operating system? Also, were all compilations done with same optimization configuration?

It is well known that different CPUs have differences in some operations, specially DIV ones that even introduced bugs in the past (i.e. the infamous Pentium DIV). Also different compilers may introduce different configurations about math processing if you didn't set one (i.e. using the "default" CPU). Maybe some assume Pentium (so it should workaround DIV operations) and other don't.

Also if it was compiled in a way that doesn't use the CPU math operations different operating systems/library versions may have different implementations for the same operation.

Regards,
Guillermo Martínez.

Show quoted text 94 lines
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 - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

James Richters
to Gabor Boros: I got different results with 32bit vs. 64bit, 3.2.2 vs. 3.3.1, FPC vs. Delphi. Why? var…

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

Earlier message 98 lines
-----Original Message----- From: fpc-pascal On Behalf Of Gabor Boros via fpc-pascal Sent: Friday, October 15, 2021 5:50 AM To: Cc: Gabor Boros 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

Reply by email

Ched
to James Richters

Hello All,

In https://wiki.freepascal.org/Variables_and_Data_Types about Strings:

  // where:  1 < length <= 255

is to read as

  // where:  1 <= length <= 255

isn't it ?

Cheers, Ched

Le 15.10.21 à 18:44, James Richters via fpc-pascal a écrit :

Show quoted text 151 lines
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 On Behalf Of Gabor Boros via fpc-pascal Sent: Friday, October 15, 2021 5:50 AM To: Cc: Gabor Boros 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 - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Ched

Well, well, understand.

OTOH, declaring a string of length 1 is sort of futile -- it uses two bytes where a plain char declaration takes just one byte.

Not so futile as a string can be empty, not a char !

Regards, Dennis, Ched'

Reply by email

Ralf Quint
to Ched
Ched wrote 6 lines
Well, well, understand. > OTOH, declaring a string of length 1 is sort of futile -- it uses > two bytes where a plain char declaration takes just one byte. Not so futile as a string can be empty, not a char !

Well, if you don't like it being called "futile, just call it "nonsense" instead (in 99.99% of all possible use cases)

Ralf

This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email