Cython gibt 0 für einen Ausdruck zurück, der mit 0,5?

8

Aus irgendeinem Grund gibt Cython 0 für einen mathematischen Ausdruck zurück, der 0,5 ergeben sollte:

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

Seltsamerweise mischen Sie Variablen ein und es wird wie erwartet funktionieren:

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

Vanilla CPython gibt in beiden Fällen 0,5 zurück. Ich kompiliere für 37m-x86_64-linux-gnuund bin auf language_leveleingestellt 3.

Was ist das für eine Hexerei?

iTayb
quelle
Welche Kompilierungseinstellungen verwenden Sie und für welche Python-Version kompilieren Sie? Ist Ihr language_levelSet auf die Python-Version eingestellt, für die Sie kompilieren? (Die Inkonsistenz ist wahrscheinlich ein Fehler, selbst wenn zwischen Ihrer language_levelund Ihrer Python-Version eine
Nichtübereinstimmung besteht
Die Frage wurde bearbeitet, um diese Details aufzunehmen. 10x
iTayb
DavidW es ist vollkommen richtig, Sie können versuchen, nur 1.0 zu verwenden, um es schweben zu lassen: print (2 ** -1.0)
Fanto

Antworten:

4

Dies liegt daran, dass C-Ints anstelle von Python-Ganzzahlen verwendet werden, sodass das C-Verhalten eher dem Python-Verhalten entspricht. Ich bin mir relativ sicher, dass dies früher irgendwo als Einschränkung dokumentiert wurde, aber ich kann es jetzt nicht finden. Wenn Sie es als Fehler melden möchten, gehen Sie zu https://github.com/cython/cython/issues , aber ich vermute, dass dies ein bewusster Kompromiss zwischen Geschwindigkeit und Kompatibilität ist.

Der Code wird übersetzt in

__Pyx_pow_long(2, -1L)

wo __Pyx_pow_long ist eine Funktion des Typs static CYTHON_INLINE long __Pyx_pow_long(long b, long e).


Der einfachste Weg, dies zu beheben, besteht darin, eine / beide Zahlen in eine Gleitkommazahl zu ändern

 print(2. ** (-1))

Als allgemeiner Kommentar zur Wahl des Designs: Menschen aus der C-Welt erwarten im Allgemeinen int operator int sie eine zurückgeben int, und diese Option wird am schnellsten sein. Python hatte dies in der Vergangenheit mit dem Teilungsverhalten von Python 2 versucht (aber uneinheitlich - die Leistung gab immer eine Gleitkommazahl zurück).

Cython versucht im Allgemeinen, dem Verhalten von Python zu folgen. Viele Leute verwenden es jedoch aus Geschwindigkeitsgründen, so dass sie auch versuchen, auf schnelle, C-ähnliche Operationen zurückzugreifen, insbesondere wenn Leute Typen angeben (da diese Leute Geschwindigkeit wollen). Ich denke, was hier passiert ist, ist, dass es möglich war, die Typen automatisch abzuleiten, und daher standardmäßig das C-Verhalten verwendet wurde. Ich vermute, dass es idealerweise zwischen bestimmten Typen und Typen unterscheiden sollte, auf die es geschlossen wird. Es ist jedoch wahrscheinlich auch zu spät, dies zu ändern.

DavidW
quelle
2

Es sieht so aus, als würde Cython fälschlicherweise auf den endgültigen Datentyp schließen, intanstatt floatnur Zahlen zu verwenden

Der folgende Code funktioniert wie erwartet:

print(2.0 ** (-1))

Unter diesem Link finden Sie eine entsprechende Diskussion: https://groups.google.com/forum/#!topic/cython-users/goVpote2ScY

Emrah Diril
quelle