我正在使用cython循环遍历大数字,这就是我test.pyx
中的内容:
cpdef int counter(int n):
cdef int count= 0
cdef int i
for i in range(n):
count += i*2
return count
正在运行
>>> counter(10000000000)
给出以下错误:
OverflowError:Python int太大而无法转换为C long
我没有使用numpy或任何其他库,只是一个简单的for
循环。有可能解决这个问题吗?
答案 0 :(得分:0)
简短答案:是的,您可以修复它,使用c类型的“ long long”而不是c类型的“ int”。
长答案和错误说明:
您在cython中的参数是一个c int(不要与python 2 int或python 3 int混淆),它们的范围是有限的。假设现代台式机/服务器的操作系统范围几乎可以确定为−2147483648至2147483647。因此显然10000000000将不适合。我们这里有一个错误,但是当您使用int类型时,为什么错误消息中提到“ long”?让我们尝试看一下代码。
查看cython生成的源此转换。由函数“ __Pyx_PyInt_As_int”处理。通过将C类型名称替换为文本模板可以清楚地创建此函数,其结果是其中包含大量的无效代码。让它工作吧。
static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) {
const int neg_one = (int) -1, const_zero = (int) 0;
const int is_unsigned = neg_one > const_zero;
第一部分代码指出函数正在使用的C类型是否为无符号。
#if PY_MAJOR_VERSION < 3
<----- snip---->
#endif
这部分代码与我们无关,仅当python对象是python 2.x int时才起作用(不要与C int或python 3.x int混淆)。
if (likely(PyLong_Check(x))) {
现在我们要到达某个地方,这是处理python2 long和python3 ints的情况
if (is_unsigned) {
<---snip a massive chunk of dead code--->
} else {
#if CYTHON_USE_PYLONG_INTERNALS
<--snip a bunch of optimisations for easy cases-->
#endif
if (sizeof(int) <= sizeof(long)) {
__PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x))
最后,我们对您的错误消息进行了解释。如果“简易情况”代码无法处理该值,则首先将其从python3 int / python2 long转换为C long。然后,将C long转换为C int。因此,在32位长的平台上,在尝试将10000000000转换为long之前,转换尝试将其转换为int失败。