This is just down to the inherent inaccuracy of floating point arithmetic. Two of your values are not exactly representable in binary floating point, 1.8
and -0.1
. So, those numbers are approximated by the closest representable values. And that means that it's quite plausible that your equation won't evaluate to exactly 7
.
Now consider your two expressions:
Val1 := (1.8 - 2.5) / -0.1;
Val2 := (A - B) / C;
The difference between these two is that Val1
is evaluated at compile time and Val2
is evaluated at runtime. Now, it's down to the compiler how the constant expression (1.8 - 2.5) / -0.1
is evaluated. To the best of my knowledge, it's not documented how that will be evaluated.
However, it is clear that the compiler uses a different evaluation method to evaluate the constant expression from that used at runtime. This program illustrates that:
{$APPTYPE CONSOLE}
uses
SysUtils, Math;
var
A, B, C: Extended;
Val1, Val2: Extended;
begin
Val1 := (1.8 - 2.5) / -0.1;
Writeln(Ceil(Val1));
A := 1.8; B := 2.5; C := -0.1;
Val2 := (A - B) / C;
Writeln(Ceil(Val2));
Writeln(BoolToStr(Val1=7.0, True));
Writeln(BoolToStr(Val2=7.0, True));
Writeln(BoolToStr(Val1<Val2, True));
Readln;
end.
Output:
7 8 True False True
So, this shows that Val1
and Val2
have different values, and that Val2
is strictly greater than 7
.
The fundamental problem you have is that of representably of floating point values. Because you are using Extended
, which uses a binary representation, your decimal input values are not exactly representable. If you want exact arithmetic here, you will need to use a decimal representation.
As always when answering variants of this question, I refer you to the essential reading on the subject: What Every Computer Scientist Should Know About Floating-Point Arithmetic.