Discrepancy between formatted numeric value and rounded value
Question: I found this weird behavior using python and numpy:

    
    
    print('%10.3f' %0.4975)
    

returns 0.497, while

    
    
    numpy.round(0.4975,3)
    

returns 0.498 as expected. With other similar numbers I always get the print
statement to deliver the correctly rounded value (for example: 0.5975 -->
0.598). Why is this? I'm using python 3.4 and numpy 1.9.2 on windows 7.


Answer: In double precision, 0.4975 is 8962163258467287/18014398509481984 which is
slightly **less** than the real number 0.4975. Hence, Python's `round`
function rounds it to 0.497.

In contrast, 0.5975 becomes 5381801554707743/9007199254740992 which is
slightly **more** than the real number 0.5975. So we get the expected 0.598
when rounding.

Why does NumPy round 0.4975 to 0.498? Its algorithm is a bit different: to
round to N digits, it multiplies the given number by the Nth power of 10,
rounds to nearest integer (preferring even), and then divides by 10^N. In the
process of multiplication by powers of 10, the direction of truncation
changes; often one will get exactly a half-integer as a result. (Example:
0.15*10 = 1.5 which is exactly 3/2, although 0.15 is not exactly 3/20).

Simply put, `np.round(x, 3)` is the same as `round(x*1000)/1000`. You can
check that both return 0.498 when applied to x = 0.4975. Indeed, in double
precision 0.4975*1000 is _exactly_ 497.5 (that is, 995/2), and the direction
of rounding is then picked correctly.

Here is a comparison of how 0.05, 0.15, 0.25, ... are rounded:

### Python

    
    
    >>> [round((2*i+1)/20, 1) for i in range(10)] 
    [0.1, 0.1, 0.2, 0.3, 0.5, 0.6, 0.7, 0.8, 0.8, 0.9]  
    

### NumPy

    
    
    >>> import numpy as np
    >>> np.around([(2*i+1)/20 for i in range(10)], 1)
    array([ 0. ,  0.2,  0.2,  0.4,  0.4,  0.6,  0.6,  0.8,  0.8,  1. ])
    

Here NumPy output is what one'd expect without thinking of binary
representation.

However, `np.around([(2*i+1)/200 for i in range(100)], 2)` shows that NumPy's
algorithm won't always match the expectation, either: there are two numbers
(0.55 and 0.57) with an odd digit at the end. The problem is that, for
example, 0.545*100 is not exactly 109/2; rather, it is
7670193115365377/140737488355328.

