1

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

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

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

1 回答 1

1

有几种不同的方法可以访问所需的精度级别。

具有 64 位的系统long通常具有 128 位long long的 s。请注意,您链接的文章说“至少64 位”。sizeof(long long)如果没有什么可做的,值得检查一下。

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

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

幸运的是,C API 中有一个“未记录”的方法可以为你复制数字的字节:_PyLong_AsByteArray. 中的评论longobject.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-01-20T18:17:31.213 回答