Lazarus

Programming => General => Topic started by: Steven Pietrobon on August 29, 2019, 03:31:09 am

Title: Problem with round function
Post by: Steven Pietrobon on August 29, 2019, 03:31:09 am
I'm getting a strange output from the round function using fpc-3.0.4.i386-win32 on Windows XP. If I perform the following

round(I+0.5)

where I is an integer, then this happens:

I is even and positive: output is I! For example round(6.5) = 6. Result should be 7! I get the correct result if I is odd.

I is odd and negative: output is -I+1. For example round(-2.5) = -2. Result should be -3! I get the correct result if I is even.

According to my turbo Pascal book round should do the following:

"Round(x: real)

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 runtime error occurs if the rounded value of x is not within the longint range."

Attached is a little program that tests this.

My question is, does anyone else get the same output?
Title: Re: Problem with round function
Post by: lucamar on August 29, 2019, 04:12:49 am
According to the RTL documentation:

Quote from: Reference for unit: System
In the case of .5, the algorithm uses "banker's rounding": .5 values are always rounded towards the even number.

IIRC, that has been the case since the times of Turbo Pascal.
Title: Re: Problem with round function
Post by: Handoko on August 29, 2019, 04:39:42 am
Hello Steven Pietrobon,
Welcome to the forum.

Actually there are about 10 kinds (or maybe more) of rounding, and as lucamar already explained that RTL uses banker's rounding.

For more information you can read here:
https://en.wikipedia.org/wiki/Rounding (https://en.wikipedia.org/wiki/Rounding)
https://www.freepascal.org/docs-html/rtl/system/round.html (https://www.freepascal.org/docs-html/rtl/system/round.html)

~edit~

I can't find information about Turbo Pascal's round function. But according to this page, it said Pascal language uses banker's rounding:
https://en.wikipedia.org/wiki/Pascal_%28programming_language%29#Data_types
Title: Re: Problem with round function
Post by: Steven Pietrobon on August 29, 2019, 05:41:40 am
Thankyou everyone for your replies.

Surely you know better than to trust Wikipedia! :-)

I have an original copy of Borland's Turbo Pascal 4.0 book from 1987. It does not say that round uses banker's rounding. It is as described in my original post. Attached is a scan of the page.
Title: Re: Problem with round function
Post by: Steven Pietrobon on August 29, 2019, 06:59:12 am
The same definition is also given Version 5.0 (page 349, pdf page 368)

https://archive.org/details/bitsavers_borlandturVersion5.0ReferenceGuide1989_16033215/page/n367
Title: Re: Problem with round function
Post by: RAW on August 29, 2019, 07:05:13 am
by the way: you can always use your own ROUND function or any of the other ROUND functions spread all over the net.  :)

For example:
https://forum.lazarus.freepascal.org/index.php?topic=10063.0
https://www.askingbox.com/tutorial/delphi-lazarus-3-ways-to-round-a-number-to-x-decimal-places
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Math_RoundTo.html
http://www.festra.com/eng/tip-rounding.htm
https://stackoverflow.com/questions/10965759/how-to-get-delphi-currency-type-to-round-like-excel-all-the-time

And you can play around with:
Round
Round own versions
RoundTo
FloatToStrF
Format
CurrToStrF
Title: Re: Problem with round function
Post by: Steven Pietrobon on August 29, 2019, 07:25:14 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.
Title: Re: Problem with round function
Post by: Handoko on August 29, 2019, 07:45:58 am
If you think Free Pascal's round function is incorrect, you can submit a report to the bugtracker forum:
http://bugs.freepascal.org/set_project.php?project_id=6 (http://bugs.freepascal.org/set_project.php?project_id=6)

But I don't think the developer team will make any changes. Most users here already knew FPC's round uses banker's rounding and we all have no issue with it. Also, changing how the current round function behaves, may cause many existing source codes work not as what it should be. It can be a nightmare.

I hate to say but it is true:
FPC is not Turbo Pascal.

If you're unsure about how certain function works, you should check the FPC/Lazarus documentation first (not TP nor Delphi). Here are some links that worth to be bookmarked:

(Free) Pascal reference guide:

http://freepascal.org/docs-html/current/ref/ref.html (http://freepascal.org/docs-html/current/ref/ref.html)

If you're new in Pascal programming? Try these:
http://www.pascal-programming.info/index.php (http://www.pascal-programming.info/index.php)
http://www.taoyue.com/tutorials/pascal/index.html (http://www.taoyue.com/tutorials/pascal/index.html)

First time using Lazarus? Read here:
http://wiki.lazarus.freepascal.org/Lazarus_Tutorial (http://wiki.lazarus.freepascal.org/Lazarus_Tutorial)

Lazarus IDE tricks (some are with animation):
http://wiki.freepascal.org/New_IDE_features_since (http://wiki.freepascal.org/New_IDE_features_since)

List of tutorials with wide range of topics (graphics, database, printer, web, etc):

http://wiki.freepascal.org/Lazarus_Documentation#Lazarus.2FFPC_.28Free_Pascal.29 (http://wiki.freepascal.org/Lazarus_Documentation#Lazarus.2FFPC_.28Free_Pascal.29)
http://wiki.freepascal.org/Category:Tutorials (http://wiki.freepascal.org/Category:Tutorials)

Some cool Pascal tricks:

http://lazplanet.blogspot.co.id/ (http://lazplanet.blogspot.co.id/)

Lazarus video tutorials:
https://wiki.lazarus.freepascal.org/Lazarus_videos (https://wiki.lazarus.freepascal.org/Lazarus_videos)
https://devstructor.com/index.php?page=tutorials (https://devstructor.com/index.php?page=tutorials)

Using examples that bundled with Lazarus installation:
Lazarus main menu > Tools > Example Projects > on the Project filter box, type the keyword for example: "sql"
Note:
Don't run it directly from there but save them first to a new location.

~edit~

I've just found the discussion about incompatibility between FPC's and TP's round function, it has been reported here:
https://bugs.freepascal.org/view.php?id=35626 (https://bugs.freepascal.org/view.php?id=35626)
Title: Re: Problem with round function
Post by: BrunoK on August 29, 2019, 09:09:25 am
The round functions means so many things that you should write your own and use it in the future so you know what it does.
That's what I have done for the last 40 years either in code and also in EXCEL.

Bankers rounding is not natural to most people /  users. It is OK if it is specified but even in accountancy firms they didn't use it.

By the way the old pascal did it differently from more recent versions of Delphi, the recent versions have so many variants that you are much better of writing your own.
Title: Re: Problem with round function
Post by: Handoko on August 29, 2019, 09:50:56 am
The round functions means so many things that you should write your own and use it in the future so you know what it does.
That's what I have done for the last 40 years either in code and also in EXCEL.

I ever worked at a software house briefly, they wrote their own rounding function too.
Title: Re: Problem with round function
Post by: Thaddy on August 29, 2019, 09:54:22 am
I ever worked at a software house briefly, they wrote their own rounding function too.
Most do: it also depends on the FPU rounding mode (to complicate things further) So even the docs are not always correct, but the default is sufficiently documented.
Title: Re: Problem with round function
Post by: Steven Pietrobon on August 29, 2019, 10:10:57 am
Do you think Free Pascal would be willing to add a switch to correct the round function, e.g., ppc386 -Borland?
Title: Re: Problem with round function
Post by: Thaddy on August 29, 2019, 10:27:01 am
Do you think Free Pascal would be willing to add a switch to correct the round function, e.g., ppc386 -Borland?
No need: you can switch the rounding mode of the FPU both in Delphi and freepascal.
Title: Re: Problem with round function
Post by: wp on August 29, 2019, 10:27:56 am
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.
Title: Re: Problem with round function
Post by: wp on August 29, 2019, 11:16:19 am
You can switch the rounding mode of the FPU both in Delphi and freepascal.
This will not make the expected results. Rounding is too complex to be mapped to the four RoundModes. One problem is in negative numbers. In my math feeling (which may be wrong...) I would expect negative values to round like the positive ones, i.e. Round(-0.5) = -1, Round(-1.5) = -2, etc. I won't get this result whichever value is applied to RoundMode (even for the positive values the result is not as expected). Therefore, the only way to guarantee the result required is to write your own rounding function.
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   Math;
  5.  
  6. // Round half away from zero rule
  7. // https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero
  8. function MyRound(x: Double): Integer;
  9. begin
  10.   if x >= 0 then
  11.     Result := Trunc(x + 0.5)
  12.   else
  13.     Result := -Trunc(-x + 0.5);
  14. end;
  15.  
  16. begin
  17.   WriteLn('RoundMode rmNearest');
  18.   SetRoundMode(rmNearest);
  19.   WriteLn(Round(-1.5));
  20.   WriteLn(Round(-0.5));
  21.   WriteLn(Round(0.5));
  22.   WriteLn(Round(1.5));
  23.  
  24.   WriteLn('RoundMode rmUp');
  25.   SetRoundMode(rmUp);
  26.   WriteLn(Round(-1.5));
  27.   WriteLn(Round(-0.5));
  28.   WriteLn(Round(0.5));
  29.   WriteLn(Round(1.5));
  30.  
  31.   WriteLn('RoundMode rmDown');
  32.   WriteLn(Round(-1.5));
  33.   WriteLn(Round(-0.5));
  34.   WriteLn(Round(0.5));
  35.   WriteLn(Round(1.5));
  36.  
  37.   WriteLn('RoundMode rmTruncate');
  38.   SetRoundMode(rmTruncate);
  39.   WriteLn(Round(-1.5));
  40.   WriteLn(Round(-0.5));
  41.   WriteLn(Round(0.5));
  42.   WriteLn(Round(1.5));
  43.  
  44.   WriteLn('MyRound');
  45.   WriteLn(MyRound(-1.5));
  46.   WriteLn(MyRound(-0.5));
  47.   WriteLn(MyRound(0.5));
  48.   WriteLn(MyRound(1.5));
  49.  
  50.   ReadLn;
  51. end.

Output:
Code: [Select]
RoundMode rmNearest
-2
0
0
2
RoundMode rmUp
-2
0
0
2
RoundMode rmDown
-2
0
0
2
RoundMode rmTruncate
-2
0
0
2
MyRound
-2
-1
1
2
Title: Re: Problem with round function
Post by: PascalDragon 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.
Title: Re: Problem with round function
Post by: Kays 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 (https://bugs.freepascal.org/view.php?id=31644), beside other issues.

[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 (https://bugs.freepascal.org/view.php?id=35626) has to be closed right away.
Title: Re: Problem with round function
Post by: Steven Pietrobon on August 30, 2019, 06:22:05 am
[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 (https://bugs.freepascal.org/view.php?id=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.
Title: Re: Problem with round function
Post by: Handoko 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?
Title: Re: Problem with round function
Post by: RAW on August 30, 2019, 08:01:05 am
I don't like the NASA religion ...  >:D
Show them the door to the next world!
Title: Re: Problem with round function
Post by: Handoko 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.
Title: Re: Problem with round function
Post by: PascalDragon on August 30, 2019, 09:00:25 am
[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 (https://bugs.freepascal.org/view.php?id=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.
Title: Re: Problem with round function
Post by: Steven Pietrobon 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.
Title: Re: Problem with round function
Post by: julkas 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
Title: Re: Problem with round function
Post by: Steven Pietrobon 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.
Title: Re: Problem with round function
Post by: Steven Pietrobon 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!
Title: Re: Problem with round function
Post by: Thaddy 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.
Title: Re: Problem with round function
Post by: julkas 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

Title: Re: Problem with round function
Post by: VTwin 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.

Title: Re: Problem with round function
Post by: Thaddy 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...
Title: Re: Problem with round function
Post by: VTwin on August 31, 2019, 08:08:50 pm
Thanks Thaddy, but I already knew it was a stupid mistake. :D I neglected to check the implementation, my fault. I have used C and C++ fairly extensively in the past, and, as you point out, implementations are not standard. They don't even agree on the return type.

In my case the mistakes were restricted to graphics-related code, and the damage limited to a displaced pixel. No statistical or monetary functions were harmed.

I learned Pascal using Turbo Pascal in the 1980s, and neglected to check if the FPC and TP Round functions were the same. They are not. I don't follow your point about "clear and strict reference for the ISO" though, it seems FPC does not follow ISO here.
Title: Re: Problem with round function
Post by: Steven Pietrobon on September 01, 2019, 09:21:02 am
Here is output with {$N-} switch.

Not sure why it is not working. For some reason, ppc386 says that the $N switch does not exist!

Free Pascal Compiler version 3.0.4 [2017/10/06] for i386
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling qroot.pas
qroot.pas(5,2) Warning: Unsupported switch "$N"


Try outputting the real value like so:

Function NthRoot(b, n: Longint): Longint;
Begin
  writeln(Exp((1/n)*Ln(b)));
  NthRoot := Trunc(Exp((1/n)*Ln(b)));
End;


Here is the result I get (Windows XP 32-bit)

 2.00000000000000000000E+0000
ta[v] = 8, ir = 2
 3.00000000000000000022E+0000
ta[v] = 27, ir = 3
 4.00000000000000000000E+0000
ta[v] = 64, ir = 4
 5.00000000000000000000E+0000
ta[v] = 125, ir = 5
Title: Re: Problem with round function
Post by: Thaddy on September 01, 2019, 10:04:25 am
The N switch is simply not supported. File a report.
Title: Re: Problem with round function
Post by: BrunoK on September 01, 2019, 12:26:38 pm
As previously written, anybody using CEIL, TRUNC, ROUND must understand what the intent of the used function is and know the kind of numbers that would be processed.
This is due to small differences in mathematical / arithmetic operations on double.
Not being aware of that fact may mean you can have horribly wrong results.
AND no, it is NOT a BUG.

Example program :
Code: Pascal  [Select][+][-]
  1. program NthRoot;
  2.  
  3. function NThRoot(b, n : integer):double;
  4. begin
  5.   Result := Exp((1/n)*Ln(b));
  6. end;
  7.  
  8. var
  9.   dbl : double;
  10.   b, n : integer;
  11. begin {NThRoot test}
  12.   {$ifdef cpu32}
  13.   WriteLn('cpu32');
  14.   {$ELSE}
  15.     {$ifdef cpu64}
  16.     WriteLn('cpu64');
  17.     {$ELSE}
  18.     WriteLn('cpu ???');
  19.     {$ENDIF}
  20.   {$ENDIF}
  21.   for b in [8,27,64,125] do begin
  22.     dbl := nThRoot(b ,3);
  23.     writeln('nThRoot(',b,', 3) = ',dbl,' trunc(nThRoot) = ', trunc(dbl));
  24.   end;
  25.   readln;
  26. end.  {NThRoot test}        
  27.  
Results :
Code: Pascal  [Select][+][-]
  1. cpu32
  2. nThRoot(8, 3) =  2.0000000000000000E+000 trunc(nThRoot) = 2
  3. nThRoot(27, 3) =  3.0000000000000000E+000 trunc(nThRoot) = 3
  4. nThRoot(64, 3) =  4.0000000000000000E+000 trunc(nThRoot) = 4
  5. nThRoot(125, 3) =  5.0000000000000000E+000 trunc(nThRoot) = 5
  6.  
Code: Pascal  [Select][+][-]
  1. cpu64
  2. nThRoot(8, 3) =  1.9999999999999998E+000 trunc(nThRoot) = 1
  3. nThRoot(27, 3) =  2.9999999999999996E+000 trunc(nThRoot) = 2
  4. nThRoot(64, 3) =  3.9999999999999991E+000 trunc(nThRoot) = 3
  5. nThRoot(125, 3) =  5.0000000000000009E+000 trunc(nThRoot) = 5
  6.  
Title: Re: Problem with round function
Post by: Thaddy on September 01, 2019, 12:34:31 pm
Well, the non-conformation to ISO in any ISO mode IS a bug.... How would you argue against it? <bemused, not worth a  >:D  grumpy>
Title: Re: Problem with round function
Post by: Kays on September 02, 2019, 01:37:44 am
[…] Rounding is not influenced by the modes.
Huh? Well, then issue #35626 (https://bugs.freepascal.org/view.php?id=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. […]
Alright, I see.

[…]
Not sure why it is not working. For some reason, ppc386 says that the $N switch does not exist! […]

qroot.pas(5,2) Warning: Unsupported switch "$N"
[…]
It doesn’t say, it doesn’t exist, but it’s ignored, since it’s unsupported.

The N switch is simply not supported. File a report.
No, don’t. It’s documented, that it’s recognized for compatibility only (https://www.freepascal.org/docs-html/prog/progsu106.html).
Title: Re: Problem with round function
Post by: Steven Pietrobon on September 02, 2019, 01:56:46 am
As previously written, anybody using CEIL, TRUNC, ROUND must understand what the intent of the used function is and know the kind of numbers that would be processed.
This is due to small differences in mathematical / arithmetic operations on double.
Not being aware of that fact may mean you can have horribly wrong results.
AND no, it is NOT a BUG.

Are you sure? The trunc function is working correctly, but the 64 bit CPU real calculation is giving less accurate results than the 32 bit CPU real calculation!!!
Title: Re: Problem with round function
Post by: Thaddy on September 02, 2019, 06:22:15 am
Are you sure? The trunc function is working correctly, but the 64 bit CPU real calculation is giving less accurate results than the 32 bit CPU real calculation!!!
Well, that's only on windows... as documented...
Title: Re: Problem with round function
Post by: PascalDragon on September 02, 2019, 10:10:50 am
The N switch is simply not supported. File a report.
No, don’t. It’s documented, that it’s recognized for compatibility only (https://www.freepascal.org/docs-html/prog/progsu106.html).
Though that could change depending on the outcome of bug report #35626 (https://bugs.freepascal.org/view.php?id=35626).

As previously written, anybody using CEIL, TRUNC, ROUND must understand what the intent of the used function is and know the kind of numbers that would be processed.
This is due to small differences in mathematical / arithmetic operations on double.
Not being aware of that fact may mean you can have horribly wrong results.
AND no, it is NOT a BUG.

Are you sure? The trunc function is working correctly, but the 64 bit CPU real calculation is giving less accurate results than the 32 bit CPU real calculation!!!
Only the i386 and i8086 targets as well as the x86_64 ones with the exception of Win64 have a separate Extended (10-bit floating point) type. All other targets have Extended as an alias to Double, because their FPUs do not support 10-bit floating point numbers. As the compiler always calculates with the highest available precision there will be differences between the platforms.
Title: Re: Problem with round function
Post by: Steven Pietrobon on September 03, 2019, 06:56:32 am
Thanks for that explanation PascalDragon. I'm a bit puzzled why x86_64 win32 supports extended (10 byte real), while x86_64 win64 only supports double (8 byte real). Is this something Intel did to increase speed?
Title: Re: Problem with round function
Post by: Thaddy on September 03, 2019, 09:15:20 am
No, it is simply that Microsoft changed their ABI for Windows64 to only support double. There are ways - undocumented and not supported - to compile FPC to support 80 bit precision under Windows 64 but you would loose MS ABI compatibility for 64 bit Windows. I seem to remember Florian himself wrote here on how to do that...(about 1-2 years ago? )
Microsoft made the choice to only support double (or multiples of double) and it has nothing to do with Intel. The hardware still supports it, hence you CAN compile FPC x86_64-win64 to use the 80 bit precision. If you know what you are doing... MS decided to only support SSE and AVX families...
Title: Re: Problem with round function
Post by: Steven Pietrobon on September 04, 2019, 06:38:59 am
Thanks Thaddy. Seems like a dumb decision by Microsoft. This means that if you want more precision than 8 bytes, you need to do your calculations in software!

Perhaps Free Pascal needs to add these software floating point options, so that extended is true extended (10 bytes), as well as adding triple and quadruple for 12 and 16 byte precision.
Title: Re: Problem with round function
Post by: Thaddy on September 04, 2019, 08:32:14 am
This means that if you want more precision than 8 bytes, you need to do your calculations in software!
Well, not quite, but it - as it stands - requires some usually simple assembler routines and all the required instructions are supported up to even 512 bits ( if the processor supports it ).
(MS C(++) achieves the same with intrinsics for 128,256 and 512 bits)
I would not be surprised if FPC supports similar on a high language level in the future.  There are already rudimentary signs of this in the compiler code,
Title: Re: Problem with round function
Post by: PascalDragon on September 09, 2019, 10:14:31 am
Perhaps Free Pascal needs to add these software floating point options, so that extended is true extended (10 bytes), as well as adding triple and quadruple for 12 and 16 byte precision.
It is indeed planned to at least support 10-Byte floating point in software, cause currently it's not trivially possible to cross compile the compiler from x86_64-win64 to i386-win32 (or any other platform without Extended support to i386).
TinyPortal © 2005-2018