Cython returns 0 对于应该评估为 0.5 的表达式?

Cython returns 0 for expression that should evaluate to 0.5?

出于某种原因,Cython 在应计算为 0.5 的数学表达式上返回 0:

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

奇怪的是,混合变量,它会按预期工作:

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

Vanilla CPython returns 两种情况都为 0.5。我正在编译 37m-x86_64-linux-gnulanguage_level 设置为 3

这是什么巫术?

这是因为它使用 C 整数而不是 Python 整数,所以它匹配 C 行为而不是 Python 行为。我相对确定这曾经被记录为某处的限制,但我现在找不到它。如果您想将其报告为错误,请转到 https://github.com/cython/cython/issues,但我怀疑这是为了兼容性而故意牺牲速度。

代码被翻译成

__Pyx_pow_long(2, -1L)

其中 __Pyx_pow_longstatic CYTHON_INLINE long __Pyx_pow_long(long b, long e).

类型的函数

最简单的修复方法是将 one/both 个数字更改为浮点数

 print(2. ** (-1))

作为对设计选择的一般评论:来自 C 世界的人通常期望 int operator int 到 return 和 int,并且此选项将是最快的。 Python 过去曾尝试使用 Python 2 除法行为来做到这一点(但不一致 - power 总是 returned 一个浮点数)。

Cython 通常会尝试遵循 Python 行为。然而,很多人为了速度而使用它,所以他们也试图回退到快速的、类似 C 的操作,尤其是当人们指定类型时(因为那些人​​想要速度)。我认为这里发生的事情是它能够自动推断类型,因此默认为 C 行为。我怀疑理想情况下它应该区分指定类型和推断的类型。但是,现在开始改变它也可能为时已晚。

当仅涉及数字时,Cython 似乎错误地将最终数据类型推断为 int 而不是 float

以下代码按预期工作:

print(2.0 ** (-1))

有关相关讨论,请参阅此 link:https://groups.google.com/forum/#!topic/cython-users/goVpote2ScY