Round and Trunc do not work fine

Can you help me please ?

I am usind TMS Scripter with Delphi XE6

// My var UFDIA30 is a Double

my value of UFDIA30 is 24545.23

ShowMessage('"UFDia30" rounded: ' + FormatFloat('$ ####.####,##',Round(UFDia30)));

The above showmessage show me $ 24,545 and is OK !

// now, the problem

UFDia30 := UFDia30 + 7;
ShowMessage('"UFDia30" rounded: ' + FormatFloat('$ ####.####,##',Round(UFDia30)));

The above showmessage show me -$ 1,224,573,769 !!!!

// but

ShowMessage(FormatFloat('$ ####.####,##',Round(24545.23 + 7))); // Show me 24,552 is fine !!!

// now the problem

ShowMessage(FormatFloat('$ ####.####,##',Round(UFDIA30 + 7))); // Show me -$ 1,224,573,762 !!!

Adrián

It's always helpful and time-saving if you send us a sample project with steps to reproduce the issue. See project attached, it works fine here

TestScripterRound.zip (7.3 KB)

Thank you Wagner.

The same project, but a little change in the Script:


Works fine !

// Now the loop with 100000. Why the error ?
Did I a mistake in some instruction ?

I guess the value just overflowed the maximum capacity of a 32-bit integer.

Excuse Wagner. I am apologies !!!

int: The int data type is a 32-bit two's complement integer. Its minimum value is -2,147,483,648 and the maximum 2,147,483,647 (inclusive). Generally this type is the default choice for integer values unless there is a reason (such as those mentioned above) to choose another.

I just want to add the following:

  1. The value of total with truncating is greater than the max value of a standard Integer type. See my slightly modified script below.
  2. According to the embarcadero docwiki System.Round Round returns a Int64 type, not a Integer type.
  3. Also, according the embarcadero docwiki System.Trunc Trunc also returns a Int64 type.

So, if you take the Floating point value of total and display it. You will find that the value is 2,454,523,000.001647. And if you remove everything to the right of, and including, the decimal point. You will have a value of 2,454,523,000. And that value is greater than the max value of a Integer type.

And since Scripter does not seem to allow Int64 types, as shown in the Round and Trunc methods. The value you are getting would be correct for a value larger than a Integer. And the only way to fix this, is to change the returned value for Round, Trunc, and others. To return their proper Ord Types. Which in this case is Int64.

var UFDIA30, x, total;

begin
  total := 0;
  UFDIA30 := 24545.23
  for x := 1 to 100000 do
  begin
    total := total + UFDIA30;
  end;
  ShowMessage('"UFDia30": '
    + FormatFloat('$ ####.####,##',total)+#13#13
    + '"UFDia30" rounded: '
    + FormatFloat('$ ####.####,##',Round(total)));
end;

Thank you Hagin !

Until TMS fixes the problem, you can do the following to fix it yourself.

  1. Launch your favorite text editor, Notepad++ prefered.
  2. Load uSystemLibrary.pas, you will find it in the TMS Scripter\source\core directory
  3. Goto Line #'s 229 and 230 and change tkInteger to tkInt64.
  4. Goto Line #'s 551 and 557 and change Integer to Int64
  5. Save uSystemLibrary.pas
  6. Close your Text editor.
  7. From your Windows Start Menu find TMS Scripter
  8. Launch the Packages Rebuild Tool
  9. Make sure that your IDE is selected.
  10. Click on the Install/Rebuild button.
  11. After the Rebuild is completed. Close the TMS Scripter Installer.
  12. Load up your IDE
  13. Load your project into the IDE and rebuild the project.

Once you do that, rerun the modified script I posted earlier to verify that Round is working properly.

1 Like

Thank you so much Michael !!!
Today will do step by step following yours instructions

Thanks again !

Adrian

Thank you all for the contribution. We have fixed the issue here and next release will include it. Note that the implementation of RoundProc and TruncProc in uSystemLibrary also needs to be modified:

procedure TatSystemLibrary.RoundProc(AMachine:TatVirtualMachine);
begin
   with AMachine do
      ReturnOutputArg( Round( GetInputArgAsFloat( 0 ) ));
end;

procedure TatSystemLibrary.TruncProc(AMachine:TatVirtualMachine);
begin
   with AMachine do
      ReturnOutputArg( Trunc( GetInputArgAsFloat( 0 ) ));
end;

Thanks Wagner

Adrian

1 Like