Recent

Author Topic: Problem with round function  (Read 3813 times)

PascalDragon

  • Hero Member
  • *****
  • Posts: 1957
  • Compiler Developer
Re: Problem with round function
« Reply #15 on: August 29, 2019, 11:32:08 am »
So what does this mean? Will Free Pascal correct round to its original definition? Add a switch that allows the original definition to be used? Or just ignore the problem? Not doing anything means that original Turbo Pascal code may not work correctly due to round being implemented incorrectly.
Unlike Turbo Pascal FPC implements floating point types using the FPU and rounding is implemented on most platforms using the FPU thus the rounding is depending on the specific rounding functionality of the FPU. Thus this won't be fixed and is by design (though we should probably document that this is a known incompatibility).

There is already a switch {$mode TP}, but it also does Banker's rounding (unlike TP7.0). I think this is a bug here clearly. You should file a bug report.
Rounding is not influenced by the modes.

Kays

  • Full Member
  • ***
  • Posts: 206
  • Whasup!?
    • KaiBurghardt.de
Re: Problem with round function
« Reply #16 on: August 29, 2019, 12:37:41 pm »
If you think Free Pascal's round function is incorrect, you can submit a report to the bugtracker forum:[…]
No need, bug reports have been filed and resolved. [PS: not “bugtracker forum”, just “bugtracker”]

See 0031644: function round return wrong values, beside other issues.

[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 has to be closed right away.
Yours Sincerely
Kai Burghardt

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #17 on: August 30, 2019, 06:22:05 am »
[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 has to be closed right away.

Oh, looks like I'm not the only one complaining about the incompatibility! However, the problem has not been fixed (at least in 3.0.4), as round still gives Banker's round for {$MODE TP} or {$MODE ISO}, instead of the Turbo Pascal round or ISO 7185 round. A slight difference between TP and ISO is that TP 4.0 and above returns a longint, while ISO returns an integer. TP 3.0 and below returned an integer.

Here is how ISO 7185 defines the round function;

http://pascal-central.com/docs/iso7185.pdf

round(x)
From the expression x that shall be of real-type, this function shall return a result of integer type. If x is positive or zero, round(x) shall be equivalent to trunc(x+0 .5) ; otherwise, round(x) shall be equivalent to trunc(x-0.5) . It shall be an error if such a value does not exist.

Examples: round(3.5) yields 4
round(-3.5) yields -4

Here is the definition given in TP 7.0, which is the same as for TP 4.0.

http://turbopascal.org/files/Turbo_Pascal_Version_7.0_Programmers_Reference_1992.pdf

Round function: System
Purpose: Rounds a real-type value to an integer-type value.
Declaration function: Round (X: Real): Longint;
Remarks: X is a real-type expression. Round returns a Longint value that is the value of X rounded to the nearest whole number. If X is exactly halfway between two whole numbers, the result is the number with the greatest absolute magnitude. A run-time error occurs if the rounded value of X is not within the Longint range.
« Last Edit: August 30, 2019, 07:08:54 am by Steven Pietrobon »

Handoko

  • Hero Member
  • *****
  • Posts: 3658
  • My goal: build my own game engine using Lazarus
Re: Problem with round function
« Reply #18 on: August 30, 2019, 07:23:02 am »
If you have any facts or useful info for the bug, you should consider to post it in the bugtracker. The developers, sometimes are too busy, they do not check this forum frequently.

---

 :-X I checked the web, it said Steven S. Pietrobon was an engineer who ever be a NASA Research Assistant. Are you the one it mentioned?

RAW

  • Hero Member
  • *****
  • Posts: 867
Re: Problem with round function
« Reply #19 on: August 30, 2019, 08:01:05 am »
I don't like the NASA religion ...  >:D
Show them the door to the next world!
Windows 7 Pro (x64 Sp1) And Windows XP Pro (x86 Sp3) - LAZARUS 2.0.8 FPC 3.0.4 - TRUNK 2.1.0 FPC 3.3.1
// This is polarity (hell) and hell is reigned by lies, nothing but lies. Be careful what you believe ...
// There are 10 types of people in this world, those who understand mind control and ...

Handoko

  • Hero Member
  • *****
  • Posts: 3658
  • My goal: build my own game engine using Lazarus
Re: Problem with round function
« Reply #20 on: August 30, 2019, 08:36:33 am »
I don't know much about NASA religion. But ever worked at NASA is awesome, I think. Sorry of being off topic. To prevent further off topic posts, I suggest to lock this thread.

PascalDragon

  • Hero Member
  • *****
  • Posts: 1957
  • Compiler Developer
Re: Problem with round function
« Reply #21 on: August 30, 2019, 09:00:25 am »
[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 has to be closed right away.
My answer explained the current state of affairs which is that the modes don't influence the rounding. Considering that Florian answered in the bug report I'll refrain myself from further comments regarding this.

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #22 on: August 30, 2019, 10:09:50 am »
If you have any facts or useful info for the bug, you should consider to post it in the bugtracker. The developers, sometimes are too busy, they do not check this forum frequently.

Thanks. Will do that.

---

Quote
:-X I checked the web, it said Steven S. Pietrobon was an engineer who ever be a NASA Research Assistant. Are you the one it mentioned?

Yes, that's me. Very grateful to NASA for the scholarship for my Ph.D. By the way, I've been using Pascal since 1986! Started off with VAX VMS Pascal (Masters degree), Sun pascal (PhD and early career), TMT Pascal (when I started my own business) and lastly Free Pascal for the last few years. Very much like the features in Free/Turbo Pascal compared to standard Pascal.

julkas

  • Hero Member
  • *****
  • Posts: 629
  • KISS principle / Lazarus 2.0.6 / FPC 3.0.4
Re: Problem with round function
« Reply #23 on: August 30, 2019, 12:06:32 pm »
Another interesting math example FPC 3.0.4
Code: Pascal  [Select][+][-]
  1. program qroot;
  2. {$ifdef FPC}
  3. {$mode TP}
  4. {$endif}
  5.  
  6. const
  7.   ta: array[0..3] of LongInt = (8, 27, 64, 125);
  8.  
  9. var
  10.   v: LongInt;
  11.   ir: LongInt;
  12.  
  13. function NthRoot(b, n: LongInt): LongInt;
  14. begin
  15.   NthRoot := Trunc(Exp((1/n)*Ln(b)));
  16. end;
  17.  
  18. begin
  19.   for v := 0 to 3 do
  20.   begin
  21.     ir := NthRoot(ta[v], 3);
  22.     WriteLn('ta[v] = ', ta[v], ', ir = ', ir);
  23.   end;
  24.   ReadLn;
  25. end.

Output on Linux 64 bit -
Code: Text  [Select][+][-]
  1. ta[v] = 8, ir = 1
  2. ta[v] = 27, ir = 2
  3. ta[v] = 64, ir = 3
  4. ta[v] = 125, ir = 4

Output on Vista 32bit -
Code: Text  [Select][+][-]
  1. ta[v] = 8, ir = 2
  2. ta[v] = 27, ir = 3
  3. ta[v] = 64, ir = 4
  4. ta[v] = 125, ir = 5

Output on DOSBOX&TP -
Code: Text  [Select][+][-]
  1. ta[v] = 8, ir = 2
  2. ta[v] = 27, ir = 3
  3. ta[v] = 64, ir = 4
  4. ta[v] = 125, ir = 5
« Last Edit: August 30, 2019, 12:14:46 pm by julkas »
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #24 on: August 31, 2019, 05:57:35 am »
The problem is that you are using trunc instead of round. If the real calculation just happens to be slightly below the correct value, e.g., 1.99999999999999999 for v = 8, then trunc will remove the fractional part, leaving the answer as 1. The real calculation depends on how the math coprocessor performs the calculation. In your case, seems that using more bits gives the incorrect result!

If you use the {$N-} switch, that should give the same answer regardless of which machine you use, since you have turned off the math coprocessor with all real calculations performed in software.
« Last Edit: August 31, 2019, 06:06:50 am by Steven Pietrobon »

Steven Pietrobon

  • New Member
  • *
  • Posts: 13
Re: Problem with round function
« Reply #25 on: August 31, 2019, 06:55:05 am »
Here's a post a made in the bug thread, which I thought would be worth reposting here.

Thinking about this some more, I think the problem stems from the limited number of round options that Intel originally implemented and that has passed on down through the ages. If we ignore nonsensical functions which round or truncate integer values to other values, then I come up with six different round functions and four truncate functions.

With round, the normal operation is to round the real to the nearest integer. The different versions come about in how mid way (0.5) values are handled. The options are

round up if positive or negative
round down if positive of negative
round up if positive and round down if negative (the ISO 7185 and Turbo Pascal method)
round down if positive and round up if negative
round to nearest even number (the only option available for Intel devices)
round to nearest odd number

For truncate, this just removes the non-integer part of the real. Here the options in what direction you round (up or down) if the non-integer part is non-zero.

round up if positive or negative (supported by Intel)
round down if positive of negative (supported by Intel)
round up if positive and round down if negative (means that only 0 will round to 0).
round down if positive and round up if negative (supported by Intel)

If we eliminate the last round method and third trunc method in the above, that would leave us eight schemes, which could have been supported with a three bit rounding code instead of the two bits that Intel used.

In any case, software developers should have known the limitations of the rounding function used by Intel, with only one option provided. The TP and ISO trunc function is supported by Intel and is selected using RC Field = 11 (the so called Chop toward 0). It would have been very easy to define round the same way that ISO defines round:

function round(x:real):longint;
begin{round}
  if x >= 0
     then round := trunc(x+0.5)
     else round := trunc(x-0.5);
end;{round}

This would have avoided any differences between the standard and what ever math coprocessor was used, regardless of the real type used. Nah! The past developers said sod this! We'll just use whatever round function is available, even if its different to the standard!

Thaddy

  • Hero Member
  • *****
  • Posts: 10293
Re: Problem with round function
« Reply #26 on: August 31, 2019, 11:23:36 am »
No, they did not say that. I suppose that at least for {$mode iso} and {$mode extendedpascal} this issue will be solved. The evidence is well documented.
I am more like donkey than shrek

julkas

  • Hero Member
  • *****
  • Posts: 629
  • KISS principle / Lazarus 2.0.6 / FPC 3.0.4
Re: Problem with round function
« Reply #27 on: August 31, 2019, 01:30:45 pm »
If you use the {$N-} switch, that should give the same answer regardless of which machine you use, since you have turned off the math coprocessor with all real calculations performed in software.
Here is output with {$N-} switch. OS - Windows Vista 32bit, CPU - Intel Pentium Dual E2200.
FPC 3.0.4, Virtual Pascal 2.1.279, DOSBOX&TP -
Code: Text  [Select][+][-]
  1. ta[v] = 8, ir = 2
  2. ta[v] = 27, ir = 3
  3. ta[v] = 64, ir = 4
  4. ta[v] = 125, ir = 5
GNU Pascal 20070904 -
Code: Text  [Select][+][-]
  1. ta[v] = 8, ir = 1
  2. ta[v] = 27, ir = 2
  3. ta[v] = 64, ir = 3
  4. ta[v] = 125, ir = 5

And now output for same code on Linux 64bit, FPC 3.0.4 -
Code: Text  [Select][+][-]
  1. ta[v] = 8, ir = 1
  2. ta[v] = 27, ir = 2
  3. ta[v] = 64, ir = 3
  4. ta[v] = 125, ir = 4
Outout for gpc 20070904 Linux 64bit -
Code: Text  [Select][+][-]
  1. ta[v] = 8, ir = 1
  2. ta[v] = 27, ir = 2
  3. ta[v] = 64, ir = 3
  4. ta[v] = 125, ir = 5
Code source - http://ideone.com/sOpVAl

procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;

VTwin

  • Hero Member
  • *****
  • Posts: 916
  • Former Turbo Pascal 3 user
Re: Problem with round function
« Reply #28 on: August 31, 2019, 04:54:51 pm »
Thanks, I appreciate this thread.

I have a vague recollection now about banker's rounding being implemented, but I just checked several of my large projects and found about 40 instances where I called Round expecting the ISO 7185 result. 

In each case except one, I had already included my own math unit after FP units, so it was a quick fix to implement ISO rounding for all platforms.

« Last Edit: August 31, 2019, 05:59:29 pm by VTwin »
“Talk is cheap. Show me the code.” -Linus Torvalds

macOS 10.13.6: Lazarus 2.0.8 (64 bit Cocoa, also fixes and trunk)
Ubuntu 18.04.3: Lazarus 2.0.8 (64 bit on VBox)
Windows 7 Pro SP1: Lazarus 2.0.8 (64 bit on VBox)

Thaddy

  • Hero Member
  • *****
  • Posts: 10293
Re: Problem with round function
« Reply #29 on: August 31, 2019, 07:03:49 pm »
You would be in for a "nice" surprise if you were using C. There is no default, so the above may confuse even more. ( it is plain stupid to ignore FPU mode!!)
In Pascal, there is a very clear and strict reference for the ISO modes. Florian likes very clear and very strict...
I am more like donkey than shrek

 

TinyPortal © 2005-2018