Question

While maintaining some code, I came across this statement:

 sActDiln := Format('%.*f',[tdDigits.ndd, Fields[itd].AsFloat * rfc / 100]);

In order to see what was going on, I added a temporary variable (actDiln) of type DOUBLE and altered the code as follows:

 actDiln := Fields[itd].AsFloat * rfc / 100;
 sActDiln := Format('%.*f',[tdDigits.ndd, actDiln]);

When "Fields[itd].AsString" is 35 and "rfc" is 109, the computed value changed from 38.15 to 38.14999999. When the number of decimal digits was 1, this then changed the computed value from 38.2 to 38.1. And this caused other problems.

I did not anticipate that using this temporary variable would cause such problems. Can anyone explain what is going on here? And what is best practice in the future to avoid this?

This demonstrates the problem:

Uses DB, DBISAMTb;

procedure TForm1.FormShow(Sender: TObject);
   var
      t : TDBISAMTable;
      actDiln, rfc : double;
      actDilnE : extended;
      sActDiln1, sActDiln2, sActDiln3 : string;
   begin
   t := TDBISAMTable.Create(Application);

   WITH t DO BEGIN
      TableName := 'xxx';
      DataBaseName := 'Study';

      Active := False;
      Exclusive := False;
      IF Exists THEN DeleteTable;

      WITH FieldDefs DO BEGIN
         Clear;
         Add('fld', ftString, 10, False);
         END;
      WITH IndexDefs DO BEGIN
         Clear;
         END;
      CreateTable;
      Exclusive := True; //<<<<<<<<<<<<<
      IndexName := '';
      Open;
      Append;
      FieldByName('fld').AsString := '35';
      Post;

      rfc := 109;

      actDiln := Fields[0].AsFloat * rfc / 100;
      sActDiln1 := Format('%.*f',[1, Fields[0].AsFloat * rfc / 100]);
      sActDiln2 := Format('%.*f',[1, actDiln]);
      actDilnE := Fields[0].AsFloat * rfc / 100;
      sActDiln3 := Format('%.*f',[1, actDilnE]);
      ShowMessage(sActDiln1 + ' vs ' + sActDiln2 + ' vs ' + sActDiln3);
      end;
   end;
Was it helpful?

Solution

Inline floating-point calculations are usually of Extended type. Check the behavior when your intermediate variable is Extended too.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top