【问题标题】:How do languages such as Python overcome C's Integral data limits?Python 等语言如何克服 C 的 Integral 数据限制?
【发布时间】:2010-10-26 10:15:12
【问题描述】:

在用 C、Python 和 Scheme 中的阶乘程序进行一些随机实验时。我遇到了这个事实:

在 C 中,使用“unsigned long long”数据类型,我可以打印的最大阶乘为 65。即“9223372036854775808”,即指定的 19 位 here

在 Python 中,我可以找到一个大到 999 的数字的阶乘,它由大量数字组成,远远超过 19。

CPython 如何实现这一点?它是否使用像 'octaword' 这样的数据类型?

我可能在这里遗漏了一些基本事实。因此,我将不胜感激阅读一些见解和/或参考资料。谢谢!

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

更新 2:我在源代码中寻找 Python 的“bignum”实现。它究竟在哪里?它在这里http://svn.python.org/view/python/trunk/Objects/longobject.c?view=markup。谢谢白沙帕扬。

【问题讨论】:

  • 我想一个更好的问题可能是,Python 如何在不影响性能的情况下使用 bignums?它是否使用 32 位整数并在需要时将它们提升为大数?这是否意味着要检查每个积分运算?
  • CPython 2.x 有 int 和 long。 int 就像 C 的 int,long 是 bignum。它会在需要时进行推广。从 CPython 3.x 开始,它们合并为单一类型并且性能较慢。
  • @kcwu,仅仅因为它们是一种数据类型而不是两种数据类型,并不意味着性能更差。

标签: python c types integer


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 为了清楚起见,使用 GMP (gmplib.org) 之类的库在纯 C 中执行任意精度算术是完全可能的。使用它编写阶乘程序相当简单。
      • 我什么时候说不可能了?
      • 我并不是要暗示你这么说。
      • 而你实际上也没有! ;-)
      【解决方案4】:

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

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

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

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

      也许 Python 正在其虚拟机中执行类似的操作。您可能需要阅读任意精度算术上的 this article 以获取详细信息。

      【讨论】:

      • Frederick 是对的,但这段代码应该被视为概念证明,而不是推荐的设计。真正的任意精度库,如 GMP (gmplib.org) 或 BigInteger 运行效率更高,并且不会不必要地依赖基数 10。
      • 顺便说一句:在原生支持 BCD 算术的处理器上,通常(或曾经)在 base 10 中执行 bignums 以简化代码的人机交互部分。 '当然,这需要支持 BCD 类型的程序集或编译器...
      【解决方案5】:

      查看 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 类型的实际可用接口然后在longobject.h 中定义,方法是像这样创建一个新类型 PyLongObject -

      typedef struct _longobject PyLongObject;
      

      等等。

      longobject.c 内部发生了更多事情,您可以查看这些以了解更多详细信息。

      【讨论】:

      • 非常感谢! longobject.c 它是 :) 我只是查看了源代码的 Python/ 子目录,错过了它在 Python 中的所有对象的事实!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-20
      • 1970-01-01
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-13
      相关资源
      最近更新 更多