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?


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.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.