Comparing with tolerance is the only way of comparing floats isn't it?
I wrote a little test
procedure RunCompare(Epsilon: Double);
const
Base: Double = 0.1;
var
i: Integer;
res: Double;
begin
res := 0;
for i := 0 to MaxInt do
begin
if CompareValue(res, Base*i, Epsilon) <> EqualsValue then
begin
WriteLn( Format('Epsilon is %.17f: deviation at step %d', [Epsilon, i]) );
Exit;
end;
res := res + Base;
end;
end;
procedure TestCompare;
var
i: Integer;
EpsilonDiv: Int64;
begin
RunCompare(0);
EpsilonDiv := Trunc(10E16);
for i := 0 to 16 do
begin
RunCompare(1/EpsilonDiv);
EpsilonDiv := EpsilonDiv div 10;
end;
end;
it outputs
Epsilon is 0,00000000000000000: deviation at step 8
Epsilon is 0,00000000000000001: deviation at step 3
Epsilon is 0,00000000000000010: deviation at step 8
Epsilon is 0,00000000000000100: deviation at step 29
Epsilon is 0,00000000000001000: deviation at step 73
Epsilon is 0,00000000000010000: deviation at step 262
Epsilon is 0,00000000000100000: deviation at step 928
Epsilon is 0,00000000001000000: deviation at step 2512
Epsilon is 0,00000000010000000: deviation at step 7415
Epsilon is 0,00000000100000000: deviation at step 23039
Epsilon is 0,00000001000000000: deviation at step 75679
Epsilon is 0,00000010000000000: deviation at step 261471
Epsilon is 0,00000100000000000: deviation at step 942813
Epsilon is 0,00001000000000000: deviation at step 2489005
Epsilon is 0,00010000000000000: deviation at step 7379011
Epsilon is 0,00100000000000000: deviation at step 23073610
Epsilon is 0,01000000000000000: deviation at step 76188297
Epsilon is 0,10000000000000001: deviation at step 264487878
0 is the value auto-calculated from both operands. As you can see, this epsilon starts to fail already after 8th step. So it seems one should provide explicit sane Epsilon for each Same|CompareValue call to be sure the desired result is achieved