Decimal ROUND_HALF_EVEN Default

3

3c273

Hello,

I'm just curious as to why the default rounding in the decimal module is
ROUND_HALF_EVEN instead of ROUND_HALF_UP. All of the decimal arithmetic I do
is rounded half up and I can't think of why one might use round half even. I
googled a bit and didn't really find a good answer. Any insight is
appreciated.

Louis
 
M

Max Erickson

3c273 said:
Hello,

I'm just curious as to why the default rounding in the decimal module
is ROUND_HALF_EVEN instead of ROUND_HALF_UP. All of the decimal
arithmetic I do is rounded half up and I can't think of why one might
use round half even. I googled a bit and didn't really find a good
answer. Any insight is appreciated.

Louis

see http://www2.hursley.ibm.com/decimal/damodel.html#refdefcont

decimal.py was written following the specification at

http://www2.hursley.ibm.com/decimal/decarith.html

max
 
T

Tim Peters

[3c273]
I'm just curious as to why the default rounding in the decimal module is
ROUND_HALF_EVEN instead of ROUND_HALF_UP.

Because it's the best (numerically "fairest") rounding method for most
people most of the time.
All of the decimal arithmetic I do is rounded half up and I can't think of
why one might use round half even.

Because you want better numeric results, or because your application
requires it. "Half-even" is also called "banker's rounding" in the
United States, because it's required in many (but not all) banking
applications.
 
L

LordLaraby

If 'bankers rounding' is HALF_ROUND_EVEN, what is HALF_ROUND_UP? I
confess to never having heard the terms.
I usually do: Y = int(X + 0.5) scaled to proper # of decimal places.
Which type of rounding is this? If either.
 
R

Raymond Hettinger

LordLaraby said:
If 'bankers rounding' is HALF_ROUND_EVEN, what is HALF_ROUND_UP? I
confess to never having heard the terms.

The terms are defined in the docs for the Context object:
http://docs.python.org/lib/decimal-decimal.html

The rounding option is one of:
------------------------------
ROUND_CEILING (towards Infinity),
ROUND_DOWN (towards zero),
ROUND_FLOOR (towards -Infinity),
ROUND_HALF_DOWN (to nearest with ties going towards zero),
ROUND_HALF_EVEN (to nearest with ties going to nearest even integer),
ROUND_HALF_UP (to nearest with ties going away from zero), or
ROUND_UP (away from zero).

I usually do: Y = int(X + 0.5) scaled to proper # of decimal places.
Which type of rounding is this? If either.

The interpreter shows that ties are rounded down towards zero:
[int(x + 0.5) for x in range(-5, 6)]
[-4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5]


Raymond
 
T

Tim Peters

[LordLaraby]
If 'bankers rounding' is HALF_ROUND_EVEN, what is HALF_ROUND_UP?

Not banker's rounding ;-). Same answer if you had said ROUND_HALF_UP
instead (which I assume you intended) -- most of these don't have
cute names.
I confess to never having heard the terms.

ROUND_HALF_UP etc are symbolic constants in Python's `decimal` module;
see the docs.
I usually do: Y = int(X + 0.5) scaled to proper # of decimal places.
Which type of rounding is this? If either.

If you meant what you said, it's not "rounding" at all, because it's
insane for negative inputs. For example, int(-2 + 0.5) = int(-1.5) =
-1, and no _rounding_ method changes an exact integer (like -2) to a
_different_ exact integer (like -1).

If you were assuming X >= 0.0, then int(X+0.5) coincides with
ROUND_HALF_UP on that domain. For X < 0.0, ROUND_HALF_UP works like
int(X-0.5).
 
B

Bengt Richter

LordLaraby said:
If 'bankers rounding' is HALF_ROUND_EVEN, what is HALF_ROUND_UP? I
confess to never having heard the terms.

The terms are defined in the docs for the Context object:
http://docs.python.org/lib/decimal-decimal.html

The rounding option is one of:
------------------------------
ROUND_CEILING (towards Infinity),
ROUND_DOWN (towards zero),
ROUND_FLOOR (towards -Infinity),
ROUND_HALF_DOWN (to nearest with ties going towards zero),
ROUND_HALF_EVEN (to nearest with ties going to nearest even integer),
ROUND_HALF_UP (to nearest with ties going away from zero), or
ROUND_UP (away from zero).

I usually do: Y = int(X + 0.5) scaled to proper # of decimal places.
Which type of rounding is this? If either.

The interpreter shows that ties are rounded down towards zero:
[int(x + 0.5) for x in range(-5, 6)]
[-4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5]
Or more explicitly:
...
int(-5 + 0.5) == int(-4.5) => -4
int(-4 + 0.5) == int(-3.5) => -3
int(-3 + 0.5) == int(-2.5) => -2
int(-2 + 0.5) == int(-1.5) => -1
int(-1 + 0.5) == int(-0.5) => 0
int( 0 + 0.5) == int( 0.5) => 0
int( 1 + 0.5) == int( 1.5) => 1
int( 2 + 0.5) == int( 2.5) => 2
int( 3 + 0.5) == int( 3.5) => 3
int( 4 + 0.5) == int( 4.5) => 4
int( 5 + 0.5) == int( 5.5) => 5

So one must be careful not to use int to convert relative screen positions to relative pixel deltas
to add to some pixel screen position, even when it's a single add that can't accumulate error or
round differentely after the add.

I guess one would want ...
int(math.floor(-4.5)) => -5
int(math.floor(-3.5)) => -4
int(math.floor(-2.5)) => -3
int(math.floor(-1.5)) => -2
int(math.floor(-0.5)) => -1
int(math.floor( 0.5)) => 0
int(math.floor( 1.5)) => 1
int(math.floor( 2.5)) => 2
int(math.floor( 3.5)) => 3
int(math.floor( 4.5)) => 4
int(math.floor( 5.5)) => 5

Which ISTM is the way some other int conversions have worked, but I can't recall the context ATM.
I.e., just trim the fractional bits from the theoretical fixed point twos complement number, which
always subtracts those positive-value fractional bits algebraically.

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,276
Messages
2,571,384
Members
48,073
Latest member
ImogenePal

Latest Threads

Top