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

Reply via email to