在python中,可以处理非常大的整数(例如uuid.uuid4().int.bit_length()
给出128),但是C-API documentation提供的最大int
数据结构是long long
,并且是64-bit int
。
我希望能够从int128
获取C PyLong
,但是似乎没有为此提供工具。例如,PyLong_AsLongLong无法处理大于2**64
的python整数。
我错过了一些文档吗,实际上是可能的吗?
当前没有可能,但是存在一些解决方法? (我想将python C-API中可用的工具用于带有int128的long long
,例如PyLong_AsInt128AndOverflow
函数)。
这是即将发布的python版本中的计划功能吗?
最佳答案
您可以通过两种不同的方法来访问所需的精度级别。
具有64位long
的系统通常具有128位long long
。请注意,您链接的文章说“至少64位”。如果没有其他事情要做,值得检查sizeof(long long)
。
假设这不是您要使用的内容,则必须仔细查看原始的PyLongObject
,它实际上是私有typedef
结构的_longobject
。
原始位可通过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);
关于python - Python C-API int128支持,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54277671/