Hi,
in the current implementation, __future__.division only applies when
dividing non-constant Python values, i.e.
from __future__ import division
a, b = 1, 2
print a / b
will print 0.5, whereas
from __future__ import division
print 1 / 2
will print 0 as the calculation happens in C space (or during constant
folding, which currently gives the same result).
http://trac.cython.org/cython_trac/ticket/343
My fix would be to handle future division in the parser (instead of code
generation, as it is now), and to let the parser directly replace "/" by
"//" when future division is *not* enabled, so that the "/" operator can
always have true division semantics when it appears inside the parse tree.
I know that these things tend to be controversial, but explicitly stating
in your code that you want "future division", and then not getting it
simply is a bug. If you want integer division, there's the "//" operator.
Now, the above is clear for the Python case. But what about C integers? If
you do this:
from __future__ import division
cdef int result = 1 / 2
print result
Cython would have to do the equivalent of this C code to be correct:
int result = 1 / ((float) 2);
but given that we generally do not fold float constants, would constant
folding be allowed in this case? And what would be the result type? Imagine
this case:
cdef int result = 1 / (1 / 2)
Running this with true division would assign 2, whereas floor division
would result in a division by zero error. Same for Python:
Python 3.1 (r31:73572, Jun 28 2009, 21:07:35)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 / (1/2)
2.0
Python 2.6.2 (r262:71600, Apr 17 2009, 11:29:30)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/(1/2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
Another example - would this get optimised:
cdef int i
for i in range(1,10,4/2):
pass
(note that the for-in-range optimisation needs to know if the step is
positive or negative - not folding the above float value into "2.0" will
prevent that)
This similarly applies to non-constants:
cdef int a = 1
cdef int result = a / 2
print result
would currently print 0 as the calculation happens in C space again. That's
ok when the result is a C integer (as that would result in doing floor
division anyway), but if the result is a Python value:
cdef int a = 1
py_result = a / 2
print py_result
Calculating the result in C space would not yield the expected Python result.
My opinion on this is: if you request true division semantics by importing
__future__.division, you should get true division in all places where you
use the "/" operator.
Comments?
Stefan
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev