# Lazarus

## Free Pascal => General => Topic started by: littlepaul476 on November 21, 2018, 10:22:43 am

Title: extended type equality
Post by: littlepaul476 on November 21, 2018, 10:22:43 am
Can someone explain to me, why this ended with <NOT OK>? Double or Real alternatives are <OK>.

Code: Pascal  [Select][+][-]
1. var i,j: extended;
2. begin
3.   i:=23500.0*0.032;
4.   j:=752.0;
5.   if i=j then
6.     <OK>
7.   else
8.     <NOT OK>;
9. end;

Lazarus 1.8.4. FPC 3.0.4, Win32
Title: Re: extended type equality
Post by: marcov on November 21, 2018, 10:28:35 am
Floating point math is not exact.

Extended on 32-bit x86 has more precision, so the deviation from the exact value suddenly fits extended. If you print i you get

7.51999999999999999944E+0002

There is a lot of information about comparing floating point values on the internet, I suggest you read it for a background.

https://floating-point-gui.de/errors/comparison/
https://bitbashing.io/comparing-floats.html

The common trick is to compare with a small deviation (if abs(x-y)<eps then instead of x=y),   free Pascal has a helper routine for that called samevalue (https://www.freepascal.org/docs-html/rtl/math/samevalue.html)
Title: Re: extended type equality
Post by: littlepaul476 on November 21, 2018, 11:28:36 am
Thanks for explanation. I checked values under Watch List and both i and j showed 752. SameValue did the trick, even with default epsilon = 0  :)
Title: Re: extended type equality
Post by: wp on November 21, 2018, 11:35:56 am
SameValue did the trick, even with default epsilon = 0  :)
The default value here is misleading. The value 0 signals to use a standard epsilon depending on the floatingpoint data type. Copied from math.pp:
Code: Pascal  [Select][+][-]
1. Const
2.   EZeroResolution = 1E-16;
3.   DZeroResolution = 1E-12;
4.   SZeroResolution = 1E-4;
5.
6. function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
7. begin
8.   if (Epsilon=0) then
9.     Epsilon:=Max(Min(Abs(A),Abs(B))*EZeroResolution,EZeroResolution);
10.   if (A>B) then
11.     Result:=((A-B)<=Epsilon)
12.   else
13.     Result:=((B-A)<=Epsilon);
14. end;
Title: Re: extended type equality
Post by: srvaldez on November 21, 2018, 01:38:34 pm
I played with this for a while
changing the expression i:=23500.0*0.032; to i:=23500.0*32/1000; made it work
I thought that casting the literal constant to extended would work, but it made no difference.

Title: Re: extended type equality
Post by: PascalDragon on November 21, 2018, 02:40:59 pm
Simply don't assume that two floating point values are equal (except when checking for special values like 0, +/- Infinity and NaN). Everything else will only lead to problems sooner or later.
Title: Re: extended type equality
Post by: Gammatester on November 21, 2018, 03:35:31 pm
Floating point arithmetic works by rounding the true result to the next representable floating point number (using the selected precision and rounding mode).

With double precision you have
Code: [Select]
`0.032 -> 0.03200000000000000066613381477509392425417900085449218750.032*23500 -> 752.00000000000001565414464721470721997320652008056640625`The last number is rounded to 752 and with FPC304/Win7 you really get OK!

OTH, for extended precision you get
Code: [Select]
`0.032 -> 0.031999999999999999998671852338705257068340870318934321403503417968750.032*23500 -> 751.999999999999999968788529959573541106010452494956552982330322265625`The last number is rounded to 751.999999999999999944488848768742172978818416595458984375, and therefore you get NOT OK.

Your expression 23500.0*32/1000 works, because all numbers are (representable as) integers and so the result must be an integer.