Let's look at the ever-shocking round statement:
>>> round(2.675, 2)
2.67
I know why round "fails"; it's because of the binary representation of 2.675:
>>> import decimal
>>> decimal.Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')
What I do not understand is: why does NumPy not fail?
>>> import numpy
>>> numpy.round(2.675, 2)
2.6800000000000002
Thinking
Do not mind the extra zeros; it's an artefact from Python's printing internal rounding. If we look at the "exact" values, they're still different:
>>> decimal.Decimal(round(2.675, 2))
Decimal('2.6699999999999999289457264239899814128875732421875')
>>> decimal.Decimal(numpy.round(2.675, 2))
Decimal('2.680000000000000159872115546022541821002960205078125')
Why oh why does NumPy behave?
I thought at first that NumPy had to handle floats using extra bits, but:
>>> decimal.Decimal(numpy.float(2.675))
Decimal('2.67499999999999982236431605997495353221893310546875')
>>> decimal.Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')
# Twins!
What is happening behind the curtains? I looked a bit at NumPy's round implementation, but I'm a Python newbie and I don't see anything overly fishy.