Проблема не в приведении, а в самом сравнении и в том, как кодируются числа с плавающей запятой.См., Например, эту статью блога, в которой подробно рассматривается значение 0,1 .Короче говоря, это значение 0,1 не кодируется как 0,1, а как 0,100000001490116119384765625 (одиночное) или 0,10000000000000000555111512312578270211815834045 (двойное) в формате IEEE-754 ...
Фактически, следующая строка
if (s = 0.1) then ShowMessage('s matched'); // fail
компилируется (по крайней мере, в x87, т.е. Delphi 32-bit) как
s := 0.1;
e := 0.1;
if s=e then
writeln('ok');
И в стандартном кодировании IEEE 0.1 не сохраняется как расширенная или одинарная точность:
s := 0.1;
e := 0.1;
writeln('s=',BinToHex(@s, SizeOf(s)));
writeln('e=',BinToHex(@e, SizeOf(e)));
//s=CDCCCC3D
//e=CDCCCCCCCCCCCCCCFB3F
Принимая во внимание, что для 0.5 нет проблемы округления:
s := 0.5;
e := 0.5;
writeln('s=',BinToHex(@s, SizeOf(s)));
writeln('e=',BinToHex(@e, SizeOf(e)));
if s=e then
writeln(ok); // it works!
// s=0000003F
// e=0000000000000080FE3F
Вы можете принудительно выполнить сравнение следующим образом:
var s, s2: single;
s := 0.1;
s2 := 0.1;
if s = s2 then
writeln('ok');
Но в любом случае, для правильного сравнения значений с плавающей запятой, SameValue()
можно использовать методы Math.pas
с соответствующим эпсилоном.