Well... as expected, pretty dismally. But after I wrote mine I started testing it to confirm it corresponded to the builtin.

Mine is as follows:

- Code: Select all
`def my_round(number,precision=0):`

scale = 10**precision

big = number*scale

big_i = int(big)

round_big = big_i+int(2*(big-big_i))

return round_big/float(scale)

- Code: Select all
`if __name__ == "__main__":`

tests = 10000

for i in range(tests):

num = randint(0,10000)+random()

prec = randint(-10,10)

builtin,mine = round(num,prec),my_round(num,prec)

results = "Test {} failed for {:.{p1}f},{p}: builtin = {:.{p}f}, mine = {:.{p}f} "

assert builtin==mine,results.format(i,num,builtin,mine,p=prec,p1=prec+1)

For the most part it performs identically (result wise), but occasionally it differs; so I investigated these exceptions. And well, it seems that for those cases when the results differed, it was mine that was correct. The built in round doesn't always handle decimals that end in a 5 consistently. And neither does my version for that matter.

So the reason for this is obviously floating point precision; but what is a good solution? It seems like a function that can't consistently round things that are as simple as:

- Code: Select all
`>>> round(0.285,2)`

0.28

>>> round(0.385,2)

0.39

I have occasionally run into these floating point precision issues and I never really know the best solution. I suppose one can always use a tolerance inequality to force the machine to admit that something like 0.9999999999999999 is really 1 but this seems like such a pain.

-Mek