Home > Mobile >  Floating Point constants vs StrToFloat not the same
Floating Point constants vs StrToFloat not the same

Time:02-23

If I compare a floating point constant to a value obtained from StrToFloat() for the same "value" I get a different results. For example:

procedure foo;
const
  d1 = 0.6694716
var
  d2: double;
begin
  d2 := StrToFloat('0.6694716');
  if d1 = d2 then
    beep;
end;

The d1 has a hex value of $B47339B4 while d2 has a hex value of $B47339B3. While they are "equal" for a comparison. They technically are not the same. From what I can tell, the const d1 is wrong. Perhaps the compiler uses the FPU and this is due to rounding?

Short of making all my constants as strings and converting them at run time. Anyone know of a work around for this?

CodePudding user response:

There are at least two defects here. In Python:

struct.pack(">d", 0.6694716).hex() == '3fe56c4fb47339b3'

This is the correct representation of the closest double precision value to 0.6694716.

But in your Delphi code d1 is 3fe56c4fb47339b4. And in 32 bit code StrToFloat yields 3fe56c4fb47339b4.

I knew that the text to float conversions in Delphi were defective. I knew that the float to text conversions in Delphi were defective. I wasn't previously aware that the compiler could not represent float literals correctly.

Whilst these operations are surprisingly tricky to get right, every major development tool has managed to do so in recent years. Delphi is lagging.

CodePudding user response:

You should never compare float-point values without a precision limit.

Use such a good function as SameValue():

if SameValue(d1, d2, 1e-7) then

CodePudding user response:

Float litterals in Delphi are Extended by default. In 64 bits, that shouldn't make any difference, but in 32 bits it does. My guess is that the parser still internally represents float litterals as a 10 byte float(extended), and then the 64 bits compiler "round it down" to 8 bytes(double) when compiling.

If my hypothesis is right, there might be nothing that can be done to circumvent that.

  • Related