Message144590
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 |
|
Date |
User |
Action |
Args |
2011-09-29 15:16:50 | ArneBab | set | recipients:
+ ArneBab |
2011-09-29 15:16:50 | ArneBab | set | messageid: <1317309410.46.0.106397423857.issue13060@psf.upfronthosting.co.za> |
2011-09-29 15:16:49 | ArneBab | link | issue13060 messages |
2011-09-29 15:16:49 | ArneBab | create | |
|