【问题标题】:Python C-API int128 supportPython C-API int128 支持
【发布时间】:2019-06-14 02:48:50
【问题描述】:

在python中可以处理非常大的整数(例如uuid.uuid4().int.bit_length()给出128),但C-API documentation提供的最大int数据结构是long long,它是64-bit int

我希望能够从 PyLong 获得 C int128,但似乎没有工具可以做到这一点。例如PyLong_AsLongLong 无法处理大于2**64 的python 整数。

  • 是否有一些我错过的文档,实际上是可能的?
  • 目前是否不可能,但存在一些解决方法? (我很想使用带有 int128 的 long long 的 python C-API 中可用的工具,例如 PyLong_AsInt128AndOverflow 函数。
  • 这是即将发布的 python 版本中的计划功能吗?

【问题讨论】:

  • 我认为您将 python 的任意长度整数与 c 的整数类型混淆了。假设uuid.uuid4().int.bit_length() == 128(并非总是如此),您可以执行print((uuid.uuid4().int * 4).bit_length()) 之类的操作,并且您应该得到一个
  • 我编辑了我的帖子,所以它更准确。我唯一想做的就是从 python PyLong 获得一个 C int128

标签: python cpython python-c-api int128


【解决方案1】:

您可以通过多种不同的方式获得所需的精度级别。

具有 64 位 longs 的系统通常具有 128 位 long longs。请注意,您链接的文章说“至少 64 位”。值得检查sizeof(long long),以防万一无事可做。

假设这不是您正在使用的,您将不得不仔细查看原始PyLongObject,它实际上是私有_longobject 结构的typedef

原始位可通过ob_digit 字段访问,长度由ob_size 给出。数字的数据类型,以及它们持有的实际引导数由typedefdigit 和宏PYLONG_BITS_IN_DIGIT 给出。后者必须小于 8 * sizeof(digit),大于 8,并且是 5 的倍数(30 或 15,取决于您的构建方式)。

幸运的是,C API 中有一个“未记录”的方法可以为您复制数字的字节:_PyLong_AsByteArraylongobject.h 中的评论内容如下:

/* _PyLong_AsByteArray: Convert the least-significant 8*n bits of long
   v to a base-256 integer, stored in array bytes.  Normally return 0,
   return -1 on error.
   If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at
   bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and
   the LSB at bytes[n-1].
   If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes
   are filled and there's nothing special about bit 0x80 of the MSB.
   If is_signed is 1/true, bytes is filled with the 2's-complement
   representation of v's value.  Bit 0x80 of the MSB is the sign bit.
   Error returns (-1):
   + is_signed is 0 and v < 0.  TypeError is set in this case, and bytes
     isn't altered.
   + n isn't big enough to hold the full mathematical value of v.  For
     example, if is_signed is 0 and there are more digits in the v than
     fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of
     being large enough to hold a sign bit.  OverflowError is set in this
     case, but bytes holds the least-significant n bytes of the true value.
*/

你应该能够得到一个类似的 UUID

PyLongObject *mylong;
unsigned char myuuid[16];

_PyLong_AsByteArray(mylong, myuuid, sizeof(myuuid), 1, 0);

【讨论】:

    猜你喜欢
    • 2019-11-12
    • 2011-05-13
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 2016-09-22
    • 2019-01-25
    相关资源
    最近更新 更多