Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exponentiation of integer constants interpreted as integer #2133

timostrunk opened this issue Mar 6, 2018 · 2 comments

Exponentiation of integer constants interpreted as integer #2133

timostrunk opened this issue Mar 6, 2018 · 2 comments


Copy link


When specifying numeric constants with the unusual syntax:
10 ** -1
cython most probably inteprets the result as integer, while the python interpreter interprets it as float.
This only affects constants and does not affect variables.

Minimal Example


test.pyx /

print (10 ** -1)
print (1E-1)
a = 10
print (a ** -1)

from distutils.core import setup
from Cython.Build import cythonize

    ext_modules = cythonize("test.pyx")


python ./ build_ext --inplace


python -c "import test" # with uncompiled


python -c "import test" # with compiled test.pyx

@scoder scoder added this to the 0.29 milestone Mar 6, 2018
Copy link

scoder commented Mar 6, 2018

A bit of an edge case, but I'm inclined to agree. If one of the two operands is a (typed) variable, the result type depends on the variable type. If both sides are literals, however, it should follow Python code semantics, which means that the result is either an arbitrary size non-negative integer or a double float. And that needs to be decided at compile time, as C is quite picky about types. ;)

This can still get tricky when the actual code is something like 10 ** (1-2), i.e. the right side is an expression rather than a literal, maybe even one that cannot safely be evaluated at compile time. Specifically, Cython does not currently do that for constant float expressions in order to avoid loss (or gain) of precision on string serialisation, so 10 ** -1 is actually not folded into a literal 0.1 in the C code.

The problem with literal IEEE-754 float expressions is really that some users might be spelling them out in a specific way (instead of using literals) because they actually rely on the exact semantics, so evaluating them at compile time with any semantics that are not strictly IEEE-754 (such as fractions.Fraction()) is straight out, and even evaluating them as Python floats and then using repr() to write them into the C code might not result in exactly the binary double float in C that users expected from the specific expression they wrote.

Long story short, I think what needs to be done is what CPython does here: if the exponent is negative, coerce both operands to double floats and evaluate the whole expression as double. For numeric literal expressions, the sign should always be available at compile time via internal constant calculation. See PowNode and its base classes in

Copy link

I'll note here for whoever wants to fix this issue the places in the documentation that will need to be changed accordingly:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet

No branches or pull requests

3 participants