New submission from Arne Babenhauserheide <[email protected]>:
Hi,
I just stumbled over round() errors. I read the FAQ¹, and even though the FAQ
states that this is no bug, its implementation is less than ideal.
To illustrate:
>>> round(0.5, 1)
0.0
and
>>> round(5, -1)
0
This is mathematically wrong and hits for comparisions which humans put in.
As alternate I use the following hack myself where ever I have to round
numbers:
def roundexact(a, *args):
... return round(a+0.000000000000001*max(1.0, (2*a)//10), *args)
This has correct behavior for *5 on my hardware:
>>> roundexact(0.5, 0)
1.0
Its errors only appear in corner cases:
>>> roundexact(0.4999999999999999, 0)
0.0
>>> roundexact(0.49999999999999998, 0)
1.0
This implementation shields me from implementation details of my hardware in
all but very few extreme cases, while the current implementation of round()
exhibits the hardware-imposed bugs in cases which actually matter to humans.
Maybe round could get a keyword argument roundup5 or such, which exhibits the
behavior that any *5 number is rounded up.
Note: The decimal module is no alternative, because it is more than factor 100
slower than floats (at least for simple computations):
>>> from timeit import timeit
>>> timeit("float(1.0)+float(0.1)")
0.30365920066833496
>>> timeit("Decimal(1.0)+Decimal(0.1)", setup="from decimal import Decimal,
>>> getcontext; getcontext().prec=17")
49.96972298622131
¹: http://docs.python.org/library/functions.html?highlight=round#round
----------
components: Interpreter Core
messages: 144590
nosy: ArneBab
priority: normal
severity: normal
status: open
title: make round() floating-point errors less hurtful
versions: Python 3.2
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue13060>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com