# [Numpy-tickets] [NumPy] #464: division inconsistent with Python; a/b inconsistent with a%b, scary scalar behaviour

NumPy numpy-tickets@scipy....
Tue Mar 6 11:27:54 CST 2007

#464: division inconsistent with Python;  a/b inconsistent with a%b, scary scalar
behaviour
----------------------------+-----------------------------------------------
Reporter:  gregsmithto     |       Owner:  somebody
Type:  defect          |      Status:  new
Priority:  normal          |   Milestone:
Component:  numpy.numarray  |     Version:  1.0.1
Severity:  normal          |    Keywords:  division
----------------------------+-----------------------------------------------
With integer {{{n/d}}} and {{{n%d}}} , if  {{{n <0}}}  and {{{d>0}}} ,
python always rounds {{{n/d}}}  to -inf and gives {{{0 <= n%d < d}}} ;
whereas numpy gives you whatever the C division does, which is usually
rounding towards zero for {{{n/d}}} . I brought this up for Numeric a few
years ago, and was informed that this had been discussed on the group and
it was done this way for performance reasons. I would have voted strongly
the other way, but that is what it is, and it wasn't such a big deal for
Numeric. However, with numpy, this behaviour is inherited by integers
extracted from arrays, which otherwise behave like Python ints. These
objects could travel an arbitrary distance into other parts of a Python
application which are completely unaware of numpy, so there is the
potential for very strange failures. Also,  it seems that numpy (unlike
Numeric) now gives the python result for {{{%}}}, but still gives the C
result for {{{/}}} (and {{{//}}}).

So we have:
* {{{(n/d)*d+(n%d) != n}}}   because {{{/}}} and {{{%}}} are
inconsistent
* {{{//}}} operator (which is called 'floor_division' internally), does
not do floor division
* very surprising behavior with scalars, as shown below.

{{{
>>> from numpy import array
>>> a,b= -7,10
>>> a,b
(-7, 10)
>>> a/b,  a%b
(-1, 3)
>>> divmod(a,b)
(-1, 3)
>>> pair=array((a,b))
>>> pair
array([-7, 10])
>>> a,b=pair
>>> a,b
(-7, 10)
>>> a/b,  a%b
(0, 3)
>>> divmod(a,b)
(0, 3)
}}}

At least it is now possible to get a future-proof,portable floor division
without needing conditionals: {{{ (n-(n%d))//d }}}, since the {{{%}}}
works.

I recognize the problems associated with changing this behaviour. But it's
already been changed (I don't know when) for {{{%}}}; and having it
propogated into the scalars creates a serious new problem which wasn't
there in Numeric. Also -- at least in principle -- the current behaviour
is platform dependent, so apps using numpy may encounter the same issue
simply by moving to a different C compiler platform.

--
Ticket URL: <http://projects.scipy.org/scipy/numpy/ticket/464>
NumPy <http://projects.scipy.org/scipy/numpy>
The fundamental package needed for scientific computing with Python.