Cython возвращает 0 для выражения, которое должно оцениваться до 0,5? - PullRequest
8 голосов
/ 12 января 2020

По какой-то причине Cython возвращает 0 в математическом выражении, значение которого должно быть равно 0,5:

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

Как ни странно, смешайте переменные, и все будет работать как положено:

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

Ваниль CPython возвращает 0,5 для обоих случаев. Я компилирую для 37m-x86_64-linux-gnu, а language_level имеет значение 3.

Что это за колдовство?

Ответы [ 2 ]

4 голосов
/ 12 января 2020

Это потому, что он использует C целых, а не Python целых чисел, поэтому он соответствует поведению C, а не Python. Я относительно уверен, что раньше это было задокументировано как ограничение, но сейчас я не могу его найти. Если вы хотите сообщить об этом как об ошибке, то go до https://github.com/cython/cython/issues, но я подозреваю, что это преднамеренный компромисс скорости для совместимости.

Код переводится в

__Pyx_pow_long(2, -1L)

, где __Pyx_pow_long - это функция типа static CYTHON_INLINE long __Pyx_pow_long(long b, long e).


Самый простой способ исправить это - изменить одно или оба числа на плавающие номер точки

 print(2. ** (-1))

В качестве общего комментария к выбору дизайна: люди из мира C обычно ожидают, что int operator int вернет int, и этот вариант будет самым быстрым. Python пытался сделать это в прошлом с поведением деления Python 2 (но непоследовательно - power всегда возвращал число с плавающей запятой).

Обычно Cython пытается следовать поведению Python. Тем не менее, многие люди используют его для скорости, поэтому они также пытаются вернуться к быстрым, C -подобным операциям, особенно когда люди указывают типы (так как эти люди хотят скорость). Я думаю, что здесь произошло то, что он мог автоматически выводить типы и поэтому по умолчанию настроен на C. Я подозреваю, что в идеале он должен различать guish между указанными типами и типами, которые он выводит. Однако, возможно, уже слишком поздно начинать изменять это.

2 голосов
/ 12 января 2020

Похоже, что Cython неправильно выводит окончательный тип данных как int, а не float, когда задействованы только цифры

Следующий код работает, как и ожидалось:

print(2.0 ** (-1))

См. Эту ссылку для связанной дискуссии: https://groups.google.com/forum/#! Topic / cython-users / goVpote2ScY

...