In my program, ROUND (0.75*2009934) = ROUND (1507450.5)= 1,507,450.
With Turbo Pascal 6.0, this value rounded to 1,507,451.
ROUND(1.5) = 2
ROUND(2.5) = 2
ROUND(3.5) = 4
ROUND(4.5) = 4
ROUND (99.5) = 100
ROUND (100.5) = 100
The help on ROUND indicates that it should round to the number of
highest absolute value. (HELP is QUOTED BELOW).
Am I missing something?
The Round function rounds a real-type value to an integer-type value.
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.
If the rounded value of X is not within the Longint range, a run-time
error will be generated, which can be handled using the EInvalidOp
exception.
> Am I missing something?
The help in D1-D3 is wrong. The help has been corrected in D4:
"X is a real-type expression. Round returns an Int64 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 always the even
number."
This is called "Banker's rounding". Here's my standard text on the
topic. See the very end for a rounding function which works the way
you expect:
The Delphi documentation for the Round function is incorrect. The way
you've described Round working is the way it is supposed to work (and
has worked, since Borland Pascal 7).
That is how the Intel Numeric Processing Unit (NPU) rounds numbers by
default, and consequently that is how the Delphi Round() function
works. When the fractional part of the real is exactly 0.5 rounding
is done to the nearest =even= number.
Actually, it would be better to say that Intel chose this algorithm
because that's what IEEE floating point is supposed to do.
The following table shows why this method of rounding is necessary:
"error"
0.0 -> 0.0 0.0
0.1 -> 0.0 -0.1
0.2 -> 0.0 -0.2
0.3 -> 0.0 -0.3
0.4 -> 0.0 -0.4
0.5 -> ???
0.6 -> 1.0 0.4
0.7 -> 1.0 0.3
0.8 -> 1.0 0.2
0.9 -> 1.0 0.1
4 values are rounded down (0.1 .. 0.4) and 4 values are rounded up
(0.6 .. 0.9) and 0.0 isn't changed. If 0.5 is always rounded up, then
on average the errors would total 0.5, while if 0.5 is always rounded
down, then the average error would be -0.5.
By rounding 0.5 down half the time, and up the other half, the
average errors would balance out.
This illustrates how quickly rounding errors can accumulate in a
simple total.
IEEE "Traditional"
0.5 -> 0 1
1.5 -> 2 2
2.5 -> 2 3
3.5 -> 4 4
---------------------------------------------
Total 8 10
Error 0 2 ( 25%)
Accountants and bankers are aware of how traditional rounding can
distort their bookkeeping records over time. Hence, the IEEE
method is sometimes called "banker's rounding".
If you don't agree with the logic behind the way Delphi implements the
Round function, and you don't mind accumulating statistical errors,
then use this algorithm, which always rounds up:
function AlwaysRoundUp(X: Extended): Extended;
begin
Result := Trunc(X) + Trunc ( Frac(X) * 2 );
end;
--
Rick Rogers (TeamB) | Fenestra Technologies
http://www.fenestra.com/
You answered me too quickly. Since I posted the reply, I did a search
on the Inprise bulletin boards and found your statement of 19-Jan-98.
I went here to remove my posted question, but you had already answered.
Thanks for the very quick reply. I understand the mathematical reason
for the "bankers rounding".
I was just trying to match to output created by Turbo 6.0 and was
researching why it was different with D3. Then I went to Delphi help
screens and wondered why my results were different than what help
implied.
Thanks. I should have searched the bulletin boards BEFORE I posted my
question.
>How come when I round an even number plus one half, Delphi rounds down?
It doesn't. It rounds x.5 to the nearest even number (Bankers round).
Yorai Aminov (TeamB)
http://ourworld.compuserve.com/homepages/yaminov
> I went here to remove my posted question, but you had
> already answered.
Sorry, I'll try to answer a little slower next time :). It has been a
common question/complaint for years -- and TeamB did what it could to
ensure Inprise got the docs right in D4.
Jim Schoen wrote in message <35B8ED...@execpc.com>...
>How come when I round an even number plus one half, Delphi rounds down?
> I wonder if there is any way to specify/switch rounding methods?
There is, it involves flipping a bit in the Intel FPU. Or you could
use the other AlwaysRoundUp function which I posted in my other
message.
> There is, it involves flipping a bit in the Intel FPU. Or you could
> use the other AlwaysRoundUp function which I posted in my other
> message.
Please someone correct me if I'm wrong, but it would appear that the FPU
has no way of performing 'standard' rounding. It has 4 rounding modes,
none of which correspond to 'standard' rounding.
It seems strange that if you use:
Format ('%.0f, [ n ])
to convert a real 'n' to a text 'integer', then you do get standard
rounding (x.5 always rounded up to x+1).
Dave Riley
Tangent Software Ltd, Reading, UK
> Please someone correct me if I'm wrong, but it would appear that the FPU
> has no way of performing 'standard' rounding
Actually, you know more about this than I do... I would use an OP
function to accomplish the goal, and wouldn't fool around with
switching the FPU.
> It seems strange
Agreed, you can see why this happens in SysUtils.pas.