[Tutor] Fw: About the Round Function
Danny Yoo
dyoo at hashcollision.org
Fri Apr 1 21:01:39 EDT 2016
> My students and I are interested in knowing the rationale behind Python's
> choice of the Banker's rounding algorithm to be the default rounding
> algorithm in the third release of Python.
To be specific: your question is on the toplevel round() function.
https://docs.python.org/3/library/functions.html#round
The assumption implicit in the question is that Python is the only
system that does this.
However, it's not just Python: the general "IEEE 754" standard says to do this.
https://en.wikipedia.org/wiki/Rounding#Round_half_to_even
There's more background information here:
http://www.lahey.com/float.htm
---
The rest of this is very-deep diving: if you are a beginner to Python,
I strongly recommend skipping the rest of this.
Let me double check where the rounding is happening, just for my own
peace of mind.
According the source code, in Python 2:
https://github.com/python-git/python/blob/master/Python/bltinmodule.c#L2064
it does its own thing, and we can see in in terms of floor() and ceiling().
What about in Python 3?
If we look at the latest code,
http://svn.python.org/projects/python/trunk/Python/bltinmodule.c,
and look for "builtin_round", it tells us to look at the
'_Py_double_round' function defined in floatobject.c,
http://svn.python.org/projects/python/trunk/Objects/floatobject.c
which in fact does appear to have its own implementation of rounding,
with the internal comment C:
/* The basic idea is very simple: convert and round the double to a
decimal string using _Py_dg_dtoa, then convert that decimal string
back to a double with _Py_dg_strtod. There's one minor difficulty:
Python 2.x expects round to do round-half-away-from-zero, while
_Py_dg_dtoa does round-half-to-even. So we need some way to detect
and correct the halfway cases.
Detection: a halfway value has the form k * 0.5 * 10**-ndigits for
some odd integer k. Or in other words, a rational number x is
exactly halfway between two multiples of 10**-ndigits if its
2-valuation is exactly -ndigits-1 and its 5-valuation is at least
-ndigits. For ndigits >= 0 the latter condition is automatically
satisfied for a binary float x, since any such float has
nonnegative 5-valuation. For 0 > ndigits >= -22, x needs to be an
integral multiple of 5**-ndigits; we can check this using fmod.
For -22 > ndigits, there are no halfway cases: 5**23 takes 54 bits
to represent exactly, so any odd multiple of 0.5 * 10**n for n >=
23 takes at least 54 bits of precision to represent exactly.
Correction: a simple strategy for dealing with halfway cases is to
(for the halfway cases only) call _Py_dg_dtoa with an argument of
ndigits+1 instead of ndigits (thus doing an exact conversion to
decimal), round the resulting string manually, and then convert
back using _Py_dg_strtod.
*/
Suffice it to say, this is probably too much detail already.
More information about the Tutor
mailing list