Cython devuelve 0 para la expresión que debería evaluar a 0.5?

8

Por alguna razón, Cython devuelve 0 en una expresión matemática que debería evaluar a 0.5:

print(2 ** (-1))  # prints 0

Por extraño que parezca, mezcle las variables y funcionará como se esperaba:

i = 1
print(2 ** (-i))  # prints 0.5

Vanilla CPython devuelve 0.5 para ambos casos. Estoy compilando 37m-x86_64-linux-gnuy language_levelestá configurado para 3.

¿Qué es esta brujería?

iTayb
fuente
¿Qué configuración de compilación está utilizando y para qué versión de Python está compilando? ¿Está language_levelconfigurado para la versión de Python para la que está compilando? (La inconsistencia es probablemente un error, incluso si tiene un desajuste entre su language_levely su versión de Python, pero esta información es importante para diagnosticar el problema.)
soportes user2357112 Mónica
Editó la pregunta para incluir estos detalles. 10x
iTayb
DavidW tiene toda la razón, puedes intentar usar solo 1.0 para que flote: print (2 ** -1.0)
Fanto

Respuestas:

4

Se debe a que está usando entradas C en lugar de números enteros de Python, por lo que coincide con el comportamiento de C en lugar del comportamiento de Python. Estoy relativamente seguro de que esto solía documentarse como una limitación en alguna parte, pero ahora no puedo encontrarlo. Si desea informarlo como un error, vaya a https://github.com/cython/cython/issues , pero sospecho que esto es una compensación deliberada de velocidad por compatibilidad.

El código se traduce a

__Pyx_pow_long(2, -1L)

donde __Pyx_pow_longes una función del tipo static CYTHON_INLINE long __Pyx_pow_long(long b, long e).


La forma más fácil de solucionarlo es cambiar uno / ambos números para que sean un número de coma flotante

 print(2. ** (-1))

Como comentario general sobre la elección del diseño: las personas del mundo C generalmente esperan int operator intregresar un int, y esta opción será más rápida. Python había intentado hacer esto en el pasado con el comportamiento de división de Python 2 (pero inconsistentemente, la potencia siempre devolvía un número de coma flotante).

Cython generalmente intenta seguir el comportamiento de Python. Sin embargo, muchas personas lo usan para la velocidad, por lo que también intentan recurrir a operaciones rápidas, similares a C, especialmente cuando las personas especifican tipos (ya que esas personas quieren velocidad). Creo que lo que sucedió aquí es que ha sido capaz de inferir los tipos automáticamente y, por lo tanto, el comportamiento predeterminado es C. Sospecho que idealmente debería distinguir entre tipos específicos y tipos que se infiere. Sin embargo, probablemente también sea demasiado tarde para comenzar a cambiar eso.

DavidW
fuente