# [Numpy-discussion] round() bug

Charles R Harris charlesr.harris at gmail.com
Sat Aug 26 11:02:53 CDT 2006

```Hi,

On 8/26/06, Sven Schreiber <svetosch at gmx.net> wrote:
>
> Hi,
>
> is this normal behavior?:
>
> >>> import numpy as n; print n.mat(0.075).round(2); print
> n.mat(0.575).round(2)
> [[ 0.08]]
> [[ 0.57]]

In [7]: (arange(100)*.5).round()
Out[7]:
array([  0.,   0.,   1.,   2.,   2.,   2.,   3.,   4.,   4.,   4.,   5.,
6.,   6.,   6.,   7.,   8.,   8.,   8.,   9.,  10.,  10.,  10.,
11.,  12.,  12.,  12.,  13.,  14.,  14.,  14.,  15.,  16.,  16.,
16.,  17.,  18.,  18.,  18.,  19.,  20.,  20.,  20.,  21.,  22.,
22.,  22.,  23.,  24.,  24.,  24.,  25.,  26.,  26.,  26.,  27.,
28.,  28.,  28.,  29.,  30.,  30.,  30.,  31.,  32.,  32.,  32.,
33.,  34.,  34.,  34.,  35.,  36.,  36.,  36.,  37.,  38.,  38.,
38.,  39.,  40.,  40.,  40.,  41.,  42.,  42.,  42.,  43.,  44.,
44.,  44.,  45.,  46.,  46.,  46.,  47.,  48.,  48.,  48.,  49.,
50.])

It looks like numpy does round to even. Knuth has a discussion of rounding
that is worth reading, although he prefers round to odd. The basic idea is
to avoid the systematic bias that comes from always rounding in one
direction. Another thing to bear in mind is that floating point isn't always
what it seems due to the conversion between decimal and binary
representation:

In [8]: print '%25.18f'%.075
0.074999999999999997

Throw in multiplication, different precisions in the internal computations
of the fpu, rounding in the print routine, and other complications, and it
is tough to know precisely what should happen. For instance:

In [15]: '%25.18f'%(mat(0.575)*100)
Out[15]: '    57.499999999999992895'

In [16]: '%25.18f'%(around(mat(0.575)*100))
Out[16]: '    57.000000000000000000'

In [17]: '%25.18f'%(around(mat(0.575)*100)/100)
Out[17]: '     0.569999999999999951'

And you can see that .575 after conversion to IEEE floating point and
scaling was properly rounded down and showed up as .57 after the default
print precision is taken into account.

Python, on the other hand, always rounds up:

In [12]: for i in range(10) : print '%25.18f'%round(i*.5)
....:
0.000000000000000000
1.000000000000000000
1.000000000000000000
2.000000000000000000
2.000000000000000000
3.000000000000000000
3.000000000000000000
4.000000000000000000
4.000000000000000000
5.000000000000000000

Chuck
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://projects.scipy.org/pipermail/numpy-discussion/attachments/20060826/c3126865/attachment-0001.html
```