OverflowError:Python int太大而无法在for循环中转换为C long

时间:2018-03-21 08:44:12

标签: python windows cython

我正在使用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循环。有可能解决这个问题吗?

1 个答案:

答案 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失败。