[Python-3000] Rounding in Py3k

Nick Coghlan ncoghlan at iinet.net.au
Thu Aug 3 14:58:44 CEST 2006

```Some musings inspired by the rounding discussion on python-dev.

The Decimal module provides all of the rounding modes from the general decimal
arithmetic specification [1].

Both Decimal rounding methods (quantize() and to_integral()) return Decimal
instances - a subsequent explicit conversion to int() is needed if you want a
real integer (just like the builtin round()).

Normal floats, OTOH, only have easy access to truncate (through int()) and
round-half-up (through round()).

Additionally, the Decimal 'quantize' method signature is fine if you have
decimal literals, but not so good for Python where you have to write
"n.quantize(d('1e-2'))" to round to two decimal places.

The implicit Decimal->float conversion also allows Decimals to be rounded with
the round() builtin, but that can lead to errors in rounding near the limits
of floating point precision due to the use of an imprecise conversion in
Decimal.__float__():

>>> n = (1 + d("5e-16"))
>>> n
Decimal("1.0000000000000005")
>>> float(n.quantize(d('1e-15')))
1.0
>>> round(n, 15)
1.0000000000000011

Would it be worthwhile to design a common rounding mechanism that can be used
to cleanly round values to the built in floating point type, as well as being
able to access the different rounding modes for decimal instances?

For example, replace the builtin function round() with a non-instantiable
class like the following:

_TEN = decimal.Decimal(10)
class round(object):

@staticmethod
def half_up(num, ndigits=0):
if isinstance(num, decimal.Decimal):
return float(num.quantize(_TEN**(-ndigits)),
rounding = decimal.ROUND_HALF_UP)
return float(num)._round_half_up()

__call__ = half_up

@staticmethod
def down(num, ndigits=0):
if isinstance(num, decimal.Decimal):
return float(num.quantize(_TEN**(-ndigits)),
rounding = decimal.ROUND_DOWN)
return float(num)._round_down()

# etc for the other 5 rounding modes

Cheers,
Nick.

[1] The 7 decimal rounding modes:

round-down (truncate; round towards 0)
round-half-up (school rounding)
round-half-even (bankers' rounding)
round-ceiling (round towards positive infinity)
round-floor (round towards negative infinity)
round-half-down (WTF rounding :)
round-up (round away from zero)

--
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
```