Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中编写作为二进制的长整数?_Python_Struct_Biginteger - Fatal编程技术网

如何在Python中编写作为二进制的长整数?

如何在Python中编写作为二进制的长整数?,python,struct,biginteger,Python,Struct,Biginteger,在Python中,长整数具有无限精度。我想将一个16字节(128位)的整数写入文件struct最多只支持8字节整数数组具有相同的限制。有没有一种方法可以在不屏蔽和移动每个整数的情况下实现这一点 这里有一些澄清:我正在写入一个将从非Python程序读入的文件,所以pickle被删除了。所有128位都已使用。如果不想编写代码,可以将对象pickle为二进制,使用协议缓冲区(我不知道它们是否允许序列化无限制精度的整数)或BSON 但是编写一个通过移位来转储16字节整数的函数,如果不是时间关键的话,应该

在Python中,长整数具有无限精度。我想将一个16字节(128位)的整数写入文件<标准库中的code>struct最多只支持8字节整数<代码>数组具有相同的限制。有没有一种方法可以在不屏蔽和移动每个整数的情况下实现这一点


这里有一些澄清:我正在写入一个将从非Python程序读入的文件,所以pickle被删除了。所有128位都已使用。

如果不想编写代码,可以将对象pickle为二进制,使用协议缓冲区(我不知道它们是否允许序列化无限制精度的整数)或BSON


但是编写一个通过移位来转储16字节整数的函数,如果不是时间关键的话,应该不会那么困难。

两种可能的解决方案:

  • 就是你的长整数。这将以一种特殊的格式写入整数,允许再次读取,如果这是您想要的

  • 使用中的第二个代码段将长整型转换为大端字符串(如果愿意,可以很容易地将其更改为小端字符串),然后将该字符串写入文件

  • 问题在于,bigint的内部表示并不直接包含您要求的二进制数据。

    这可能无法避免“屏蔽并移位每个整数”的要求。我不确定避免掩码和移位是否意味着在Python长值上下文中

    字节如下所示:

    def bytes( long_int ):
        bytes = []
        while long_int != 0:
            b = long_int%256
            bytes.insert( 0, b )
            long_int //= 256
        return bytes
    

    然后,您可以使用struct.pack('16b',bytes)

    打包这个字节列表,我认为对于无符号整数(并忽略endianness),类似于

    import binascii
    
    def binify(x):
        h = hex(x)[2:].rstrip('L')
        return binascii.unhexlify('0'*(32-len(h))+h)
    
    >>> for i in 0, 1, 2**128-1:
    ...     print i, repr(binify(i))
    ... 
    0 '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
    1 '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
    340282366920938463463374607431768211455 '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
    
    可能在技术上满足非Python特定输出、不使用显式掩码和(我假设)不使用任何非标准模块的要求。不过并不特别优雅。

    该模块与内置的
    bin()
    函数相结合,对于简单灵活的解决方案来说似乎是一个很好的组合

    bytes = bitarray(bin(my_long)[2:]).tobytes()
    

    endianness可以通过多行代码来控制。您必须评估效率。

    为什么不将struct与无符号long-long类型一起使用两次呢

    import struct
    some_file.write(struct.pack("QQ", var/(2**64), var%(2**64)))
    

    这里记录了这一点(向下滚动以获得带有Q的表):

    这可能有点晚了,但我不明白为什么不能使用struct:

    bigint = 0xFEDCBA9876543210FEDCBA9876543210L
    print bigint,hex(bigint).upper()
    
    cbi = struct.pack("!QQ",bigint&0xFFFFFFFFFFFFFFFF,(bigint>>64)&0xFFFFFFFFFFFFFFFF)
    
    print len(cbi)
    
    bigint本身被拒绝,但如果您使用&0xFFFFFFFFFFFFFFFF将其屏蔽,则可以将其减少为8字节的int而不是16字节的int。然后上半部分也被移动和遮罩。您可能需要稍微调整字节顺序。我用了这个!标记以告诉它生成网络端字节顺序。此外,可能需要反转msb和lsb(高位字节和低位字节)。我将把它作为一个练习留给用户来决定。我想说,将内容保存为网络端将更安全,这样您就可以始终知道数据的端


    不,不要问我网络端是大端还是小端…

    在Python 3.2及更高版本中,您可以使用
    int.to_bytes
    int.from_bytes

    基于@DSM的答案,为了支持负整数和不同的字节大小,我创建了以下改进的代码片段:

    def to_bytes(num, size):
            x = num if num >= 0 else 256**size + num
            h = hex(x)[2:].rstrip("L")
            return binascii.unhexlify("0"*((2*size)-len(h))+h)
    

    这将正确处理负整数,并让用户设置字节数

    看起来他已经这样做了-标准库中的struct最多只支持8字节整数。您需要整个128位范围,还是只需要较低的64位,您需要有符号整数?可能是“无效”的重复?你能说得更具体一点,以便我能解决它吗?变量名(
    n
    vs.
    long\u int
    )有些混乱。此外,您可能应该使用
    n/=256
    n>=8
    n,b=divmod(n,256)
    而不是
    n/=256
    ,以防止Python3中出现(几乎)无限循环(或在传递浮点时)。@Apalala,@Sven Marnach。谢谢。如果使用
    long\u int,b=divmod(long\u int,256)
    :)可能会更好看。这对于负输入失败:
    hex(x)
    返回
    -0x123
    例如。@Score\u下:第一句话是“对于无符号整数”。小心
    bin()
    生成类似于
    0b0101110
    的内容,因此您需要删除
    0b
    前缀。您还需要
    tobytes()
    而不是
    tostring()