Python等语言如何克服C语言的整型数据限制?

2 投票
5 回答
2360 浏览
提问于 2025-04-15 11:36

在用C、Python和Scheme编写阶乘程序时,我做了一些随机实验,发现了一个有趣的事实:

在C语言中,使用'unsigned long long'这种数据类型,我能打印出的最大阶乘是65,它的值是'9223372036854775808',这个数字有19位,具体可以参考这里

而在Python中,我可以计算出最大为999的阶乘,这个数字的位数非常多,远超过19位。

那么,CPython是怎么做到的呢?它是否使用了像octaword这样的数据类型?

我可能遗漏了一些基本的知识,所以希望能得到一些见解或者相关的阅读资料。谢谢!

更新:感谢大家的解释。这是否意味着CPython使用了GNU多精度库(或者其他类似的库)?

更新2:我在寻找Python中'bignum'的实现,具体在哪里呢?它在这里:http://svn.python.org/view/python/trunk/Objects/longobject.c?view=markup。谢谢Baishampayan。

5 个回答

4

C语言中的数据类型,比如int,基本上是直接和处理器支持的数据类型对应的。所以,C语言中int的限制其实就是处理器硬件的限制。

不过,你也可以完全在软件中自己实现一个int数据类型。比如,你可以用一个数字数组来表示它。可能像这样:

class MyInt {
    private int [] digits;
    public MyInt(int noOfDigits) {
       digits = new int[noOfDigits];
    }
}

一旦你这样做了,你就可以使用这个类来存储任意位数的整数,只要你的内存足够。

也许Python在它的虚拟机内部做的就是类似的事情。你可以看看这篇文章,了解一下关于任意精度算术的详细信息。

6

看Python的源代码,似乎在Python 3之前,long类型是在longintrepr.h这个文件里定义的,具体是这样 -

/* Long integer representation.
   The absolute value of a number is equal to
    SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
   Negative numbers are represented with ob_size < 0;
   zero is represented by ob_size == 0.
   In a normalized number, ob_digit[abs(ob_size)-1] (the most significant
   digit) is never zero.  Also, in all cases, for all valid i,
    0 <= ob_digit[i] <= MASK.
   The allocation function takes care of allocating extra memory
   so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available.

   CAUTION:  Generic code manipulating subtypes of PyVarObject has to
   aware that longs abuse  ob_size's sign bit.
*/

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};

然后,long类型的实际使用接口是在longobject.h这个文件里定义的,通过创建一个新的类型PyLongObject,具体是这样 -

typedef struct _longobject PyLongObject;

接下来还有更多内容。

longobject.c文件里还有更多的东西,你可以去看看,了解更多细节。

9

这叫做任意精度算术。想了解更多可以看看这里:http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic

撰写回答