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

发布于 2024-07-20 11:19:08 字数 889 浏览 6 评论 0原文

使用 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。 谢谢拜山帕扬。

While doing some random experimentation with a factorial program in C, Python and Scheme. I came across this fact:

In C, using 'unsigned long long' data type, the largest factorial I can print is of 65. which is '9223372036854775808' that is 19 digits as specified here.

In Python, I can find the factorial of a number as large as 999 which consists of a large number of digits, much more than 19.

How does CPython achieve this? Does it use a data type like 'octaword' ?

I might be missing some fundamental facts here. So, I would appreciate some insights and/or references to read. Thanks!

UPDATE: Thank you all for the explanation. Does that means, CPython is using the GNU Multi-precision library (or some other similar library)?

UPDATE 2: I am looking for Python's 'bignum' implementation in the sources. Where exactly it is? Its here at http://svn.python.org/view/python/trunk/Objects/longobject.c?view=markup. Thanks Baishampayan.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

怪异←思 2024-07-27 11:19:08

这称为任意精度算术。 这里还有更多内容:http://en.wikipedia.org/wiki/Arbitrary- precision_arithmetic

It's called Arbitrary Precision Arithmetic. There's more here: http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic

怕倦 2024-07-27 11:19:08

查看Python源代码,似乎long类型(至少在Python 3之前的代码中)是在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 类型的实际可用接口然后在 < a href="http://svn.python.org/view/python/trunk/Include/longobject.h?view=markup" rel="nofollow noreferrer">longobject.h 通过创建新类型 PyLongObject像这样 -

typedef struct _longobject PyLongObject;

等等。

longobject.c,您可以查看这些内容以了解更多详细信息。

Looking at the Python source code, it seems the long type (at least in pre-Python 3 code) is defined in longintrepr.h like this -

/* 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];
};

The actual usable interface of the long type is then defined in longobject.h by creating a new type PyLongObject like this -

typedef struct _longobject PyLongObject;

And so on.

There is more stuff happening inside longobject.c, you can take a look at those for more details.

手心的温暖 2024-07-27 11:19:08

C 中的int 等数据类型直接(或多或少)映射到处理器支持的数据类型。 因此,C 的 int 的限制本质上是处理器硬件施加的限制。

但我们可以完全在软件中实现自己的 int 数据类型。 例如,您可以使用数字数组作为基础表示。 可能是这样的:

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

一旦你这样做了,你就可以使用这个类并存储包含任意数量数字的整数,只要你不耗尽内存。

也许Python正在其虚拟机中做类似的事情。 您可能需要阅读关于任意精度算术的这篇文章以获取详细信息。

Data types such as int in C are directly mapped (more or less) to the data types supported by the processor. So the limits on C's int are essentially the limits imposed by the processor hardware.

But one can implement one's own int data type entirely in software. You can for example use an array of digits as your underlying representation. May be like this:

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

Once you do that you may use this class and store integers containing as many digits as you want, as long as you don't run out memory.

Perhaps Python is doing something like this inside its virtual machine. You may want to read this article on Arbitrary Precision Arithmetic to get the details.

情绪失控 2024-07-27 11:19:08

不是八字。 它实现了 bignum 结构来存储任意精度的数字。

Not octaword. It implemented bignum structure to store arbitary-precision numbers.

找回味觉 2024-07-27 11:19:08

Python 分配给 long 整数(Python 3 中的所有 int)所需的空间——“数字”数组(基数是 2 的幂)根据需要分配。

Python assigns to long integers (all ints in Python 3) just as much space as they need -- an array of "digits" (base being a power of 2) allocated as needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文