TMS-Scripter: Different result than same routine in Delphi.

Hello Support,

the following method returns a different/wrong value in TMS-Scripter and I can not find out the reason.

procedure DetermNumberOfDigits(_Value:extended; var NumberOfDigits:Integer; var Resolution:Extended; var DisplayMask:String);
begin
  NumberOfDigits:=0;
  Resolution:=0;
  DisplayMask:= '';
  while Frac(_Value)>0 do begin
    inc(NumberOfDigits);
    _Value:=_Value*10;
  end;
  Resolution := 1 / Power(10, NumberOfDigits + 1);
  DisplayMask := '%.' + IntToStr(NumberOfDigits) + 'f';
end; 

If you run the above method as follows, the output is wrong.

procedure Button1Click(Sender: TObject);
var
_value:extended;
_NumberOfDigits:Integer;                    
_Resolution:Extended;
_DisplayMask:String;
begin
//  _value:=1.0609; // works fine
  _value:=1.0649; // wrong result !!!!!!!!
  DetermNumberOfDigits(_value,_NumberOfDigits,_Resolution,_DisplayMask);
  showmessagefmt('Value=<%s>, NumberOfDigits= <%d>, Resolution= <%s>, DisplayMask=<%s>.',[floattostr(_value),_NumberOfDigits,floattostr(_Resolution),_DisplayMask]);
end;

Example.zip (1.3 KB)

Regards.

Actually, the behavior is the same. See project attached.

TestScripterDigits.zip (9.5 KB)

Not exactly the same...
32 bits: Script wrong, Delphi right
64 bits: Script Wrong, Delphi wrong

In 64 bits, after multiplying all decimal digits, Frac(_Value) = 0,999999999998181 , and int(_Value) = 10648 !!!
The error starts after the first loop, after *10, when Frac(_Value) will be = 0,648999999999999.

Floating point math is quite hard, and I also found these Embarcadero recommendations on Extended type:

Extended offers greater precision on 32-bit Intel platform than other real types, but is less portable. Be careful using Extended if you are creating data files to share across platforms. Be aware that:

On 32-bit Intel platform, an Extended number is represented as 10 bytes (80 bits).

However, on the 64-bit Intel platform and ARM platform, the Extended type is an alias for Double , which is only 8 bytes. This difference can adversely affect numeric precision in floating-point operations. For more information, see Delphi Considerations for Multi-Device Applications.

I believe the easiest/fastest solution would be to figure out the maximum digits your parameter could have, format it as some #.########0, and work with this string, BUT, as we're talking about floating point, you could also experience some problems with some numbers when formatting. Maybe it would be somehow better, as this way you would avoid math operations or functions such as * 10 and Frac() .