Python等语言如何克服C语言的整型数据限制?
在用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 个回答
C语言中的数据类型,比如int
,基本上是直接和处理器支持的数据类型对应的。所以,C语言中int
的限制其实就是处理器硬件的限制。
不过,你也可以完全在软件中自己实现一个int
数据类型。比如,你可以用一个数字数组来表示它。可能像这样:
class MyInt {
private int [] digits;
public MyInt(int noOfDigits) {
digits = new int[noOfDigits];
}
}
一旦你这样做了,你就可以使用这个类来存储任意位数的整数,只要你的内存足够。
也许Python在它的虚拟机内部做的就是类似的事情。你可以看看这篇文章,了解一下关于任意精度算术的详细信息。
看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文件里还有更多的东西,你可以去看看,了解更多细节。
这叫做任意精度算术。想了解更多可以看看这里:http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic