# Floating-Point Comparison Routines

Go Up to Using Floating-Point Routines

## Contents

There are several not obvious problems with comparing floating-point numbers.

### Floating-Point Comparison Problems

One floating-point comparison problem is that what you see is not exactly how your numbers are represented in memory. You can have `X := 99.9999964` and `Y "= 100.000003` numbers, which both are shown as 100 but they are not equal:

``` uses
System.SysUtils;
var X, Y: Single;
begin
X := 99.9999964;
Y := 100.000003;
Writeln('X =', FloatToStr(X));
end.
```

The program outputs:

```X = 100
Y = 100
```

However if you try to compare X and Y they are not equal. An opposite example is:

``` var X:Single;
begin
X:=0.1;
Writeln('X =', FloatToStr(X));
end.
```

The program outputs:

```X = 0.100000001490116
```

Anther problem roots to finite representation of floating-point numbers. Let us compare a floating-point number with 'itself':

``` var X:Single;
begin
X:=0.1;
if X=0.1 then
Writeln('Equal')
else
Writeln('Not equal');
end.
```

The program outputs:

```Not equal
```

Why? To understand this, remember that the exact decimal 0.1 number has the binary representation as the infinite recurrent fraction 0.0(0011). Single precision X keeps only 23 bits for mantissa. Object Pascal executes all floating-point operations using Extended precision. When Object Pascal converts a Single precision X to the Extended representation having 63 bits mantissa, the program simply initialize all extra bits with zeros (not with the actual bits of 0.0(0011)). Read Finite Precision Implications for more information.

Now let us compare 0.1 in Single and Double precisions:

``` var
X:Single;
Y:Double;
begin
X:=0.1;
Y:=0.1;
if X=Y then
Writeln('Equal')
else
Writeln('Not equal');
end.
```

The program outputs:

```Not equal
```

Again Single and Double representations of 0.1 keep different numbers of mantissa bits.

### Comparison Routines

The solution providing correct comparison of floating-point numbers is using of some small Epsilon margin. If the difference of the two floating-point numbers lies within the Epsilon margin, then they are estimated as equal.

The System.Math unit provides the CompareValue, SameValue, and IsZero functions which handle floating-point comparisons. These functions have declarations like the following:

``` function CompareValue(const A, B: Extended; Epsilon: Extended): TValueRelationship;
function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
function IsZero(const A: Extended; Epsilon: Extended): Boolean;
```

Here `A` and `B` are floating-point numbers to compare and `Epsilon` is the small margin by which `A` and `B` can differ and still be considered the same value.

If the specified `Epsilon = 0`, then some reasonable default value is used implicitly. For example, the Extended version of SameValue uses the default value:

```Epsilon = Max(Min(Abs(A), Abs(B)) * 1E-16, 1E-16)
```