Differences between Matlab and Numpy and Python's `round` function
Question: ## Simplified question

Can I make Numpy agree with Matlab and Python's `round`?

Matlab 2013a:

    
    
    >> round(-0.5)
    ans =
        -1
    

Python (using a Numpy array, or just a scalar, same result):

    
    
    >>> import numpy
    >>> round(numpy.array(-0.5))
    -1.0
    

Numpy, the odd one out:

    
    
    >>> import numpy
    >>> numpy.round(numpy.array(-0.5))
    -0
    

Is this difference in round platform dependent?

## Original question

Matlab comes with a file "handel.mat" containing some audio data:

    
    
    >> which handel.mat
    C:\Program Files\MATLAB\R2013a\toolbox\matlab\audiovideo\handel.mat
    >> load handel
    >> soundsc(y) % play the short audio clip
    

I want to work with this data in Python so I use `scipy.io.loadmat` [1].
Specifically, I want to scale the audio's values to span the entire range of
16-bit signed integer, i.e., the smallest value of the audio signal gets
mapped to -2^15 and the largest one to 2^15-1. I was surprised when doing this
in Matlab gave me different results than Python:

Matlab:

    
    
    >> load handel
    >> int16(round(interp1([min(y), max(y)], [-2^15, 2^15-1], y(1:10))))
    ans =
         -1              %%% <-- Different from Python
       -253
      -3074
      -1277
        252
       1560
        772
      -1025
      -1277
      -3074
    

Python:

    
    
    In [1]: import numpy as np
    
    In [2]: import scipy.io as io
    
    In [3]: mat = io.loadmat('handel.mat')
    
    In [4]: np.int16(np.round(np.interp(mat['y'][:10], [mat['y'].min(), mat['y'].max()], [-2.0**15, 2.0**15-1.0])))
    Out[4]:
    array([[    0],      ### <-- Different from Matlab
           [ -253],
           [-3074],
           [-1277],
           [  252],
           [ 1560],
           [  772],
           [-1025],
           [-1277],
           [-3074]], dtype=int16)
    

There are actually 1231 samples (out of 73113 total) where the Python and
Matlab differ. I think I'm being careful with my types, but really, there's
very little error surface for type bugs to creep in here: `loadmat` should
infer the types from the MAT file, and int16 can't differ that much between
the two systems.

**Added** The first element of the output of the `interp`/`interp1d` commands
are both -0.5 (printing it to the 100th decimal place in both Python and
Matlab confirms this), but rounding in Numpy (`np.round`) yields 0, while
Matlab rounds it to -1. Is this a matter of Matlab rounding semantics?
**Furthermore** Python's built-in non-Numpy `round` for -0.5 gives me -1!
Whence this difference between Numpy's and Python's `round` functions? And
will Python's `round` always match Matlab's?

Windows64, Matlab 8.1 (2013a), Python 2.7.4.

[1]
<http://docs.scipy.org/doc/scipy/reference/generated/scipy.io.loadmat.html>


Answer: `numpy.round`, also known as `numpy.around`, rounds to the _nearest even
value_ for half-integers. This is **not** platform dependent, but a purposeful
implementation detail.

If you wish to have a quick round without using Python, see [this
answer](http://stackoverflow.com/a/16000851/1763356).

The summary is that there's a platform dependant hack to set rounding using
`fesetround` via `ctypes`. From the post:

    
    
    import numpy as np
    import ctypes
    FE_TONEAREST = 0x0000
    FE_DOWNWARD = 0x0400
    FE_UPWARD = 0x0800
    FE_TOWARDZERO = 0x0c00
    libc = ctypes.CDLL('libc.dylib')
    
    v = 1. / (1<<23)
    print repr(np.float32(1+v) - np.float32(v/2)) # prints 1.0
    libc.fesetround(FE_UPWARD)
    print repr(np.float32(1+v) - np.float32(v/2)) # prints 1.0000002
    

