V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
y0
V2EX  ›  Python

Python 里怎么把一个大整数变成 bytes?

  •  
  •   y0 · 2013-06-04 06:54:09 +08:00 · 6406 次点击
    这是一个创建于 4220 天前的主题,其中的信息可能已经有所发展或是发生改变。
    现在知道两种方法:

    一种是 import struct, 另一种是 import binascii.

    >>> a = 3312345
    >>> struct.pack('>I', a)
    b'\x002\x8a\xd9'
    >>> binascii.unhexlify(hex(a).lstrip('0x'))
    b'2\x8a\xd9'

    第一种的话,a 不能太大,超过 2^32 就不行了。(另外那个 \x00 还得处理掉)
    但第二种好像又不是很优雅。哪位有高招? One-liner preferred.

    a 是一个 256 bits 的数。
    15 条回复    1970-01-01 08:00:00 +08:00
    sillyousu
        1
    sillyousu  
       2013-06-04 07:06:57 +08:00 via Android
    这个256位的大数一定要变成一个bytes?

    如果可以变几个bytes的话,struct那里多放几个I行不?
    zuroc
        2
    zuroc  
       2013-06-04 07:24:06 +08:00
    In [10]: msgpack.dumps(2**64-1)
    Out[10]: '\xcf\xff\xff\xff\xff\xff\xff\xff\xff'

    In [11]: msgpack.dumps(2**64-1)
    Out[11]: '\xcf\xff\xff\xff\xff\xff\xff\xff\xff'

    In [12]: msgpack.dumps(1)
    Out[12]: '\x01'

    In [13]: msgpack.dumps(2)
    Out[13]: '\x02'

    In [14]: msgpack.dumps(0)
    Out[14]: '\x00'
    y0
        3
    y0  
    OP
       2013-06-04 07:43:02 +08:00
    @zuroc >>> msgpack.dumps(2078388773771218783740288990824871144635246987129597257065)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "_packer.pyx", line 259, in msgpack._packer.packb (msgpack/_packer.cpp:259)
    File "_packer.pyx", line 184, in msgpack._packer.Packer.pack (msgpack/_packer.cpp:184)
    File "_packer.pyx", line 124, in msgpack._packer.Packer._pack (msgpack/_packer.cpp:124)
    OverflowError: int too big to convert
    zuroc
        4
    zuroc  
       2013-06-04 08:10:09 +08:00
    max 2**64-1
    y0
        5
    y0  
    OP
       2013-06-04 08:29:37 +08:00
    @zuroc 我都说了 256 bit 了。
    lyjyiran
        6
    lyjyiran  
       2013-06-04 08:30:26 +08:00
    >>> val=2078388773771218783740288990824871144635246987129597257065
    >>> bytes = hex(val).rstrip('L')[2:].decode('hex')
    >>> bytes
    'T\xc3d+\x1bq\x8d\x7f\xb0\x12\xdf\xea\x1fd\x04\x14\xbbwG\xd6\xd1\xc8\xe5i'
    >>> int(bytes.encode('hex'),16)
    2078388773771218783740288990824871144635246987129597257065L
    clowwindy
        7
    clowwindy  
       2013-06-04 09:45:36 +08:00 via iPhone
    一个循环就搞定的事,何必这样呢
    y0
        8
    y0  
    OP
       2013-06-04 11:51:59 +08:00
    @clowwindy 没必要用循环。我最后采用的是
    binascii.unhexlify(hex(a).[2:]).
    mindcat
        9
    mindcat  
       2013-06-04 11:53:32 +08:00
    @y0 hex(2**256-1)
    具体看着办 =w=
    zuroc
        10
    zuroc  
       2013-06-04 12:13:07 +08:00
    In [5]: marshal.dumps(22222222222222222222222222222222222222222)
    Out[5]: 'l\t\x00\x00\x00\x8ecq\x1c\x8e3\xd1"\xf6\x1e5J\xfa\x08)\x12NA'

    In [6]: marshal.dumps(22222222222222222222222222222222222222222222222222)
    Out[6]: 'l\x0b\x00\x00\x00\x8ecq\x1c\x8ec\xb1Pi<AG\xb5\x0b\x0f6Yp\xd0}\xd1<'

    In [7]: marshal.dumps(2222222222222222222222222222222222222222222222222222222222222222)
    Out[7]: "l\x0f\x00\x00\x00\x8ecq\x1c\x8ecq\x1c\xae\n\x0f\n'i6?\x18\n'u\xa5Y\x11G\xcbF\xdc,\x01\x00"
    y0
        11
    y0  
    OP
       2013-06-04 15:17:25 +08:00
    @zuroc 好像字节序是反的……

    >>> binascii.unhexlify(hex(a).lstrip('0x'))
    b'2\x8a\xd9'
    >>> marshal.dumps(a)
    b'i\xd9\x8a2\x00'
    ruoyu0088
        12
    ruoyu0088  
       2013-06-09 16:58:57 +08:00
    Python3的话可以用int的to_bytes()方法。

    In [14]: a = 3**100

    a.to_bytes(a.bit_length()//8 + 1, "little")

    Out[14]:
    b'\xd1\x138\xcfU}\x94\xd6u\xf7A[Vh7g\xcaSFZ'
    y0
        13
    y0  
    OP
       2013-06-09 17:16:00 +08:00
    @ruoyu0088 嗯,昨天才学会这个。不过这个必须 20 bytes 以内。

    现在用的是

    def to_bytes(u_int,length):
    return bitstring.BitArray(uint=u_int,length=length).bytes
    xierch
        14
    xierch  
       2013-06-09 17:21:36 +08:00   ❤️ 1
    还是直接点写循环吧.. 何必纠结于一行,效率反而低了..

    i = 2078388773771218783740288990824871144635246987129597257065
    s = ''
    while i:
    s = chr(i & 255) + s
    i = i >> 8
    ruoyu0088
        15
    ruoyu0088  
       2013-06-09 19:42:26 +08:00   ❤️ 1
    @y0 没有20bytes的限制,例如:

    In [7]:

    a = 3 ** 500

    a.to_bytes(200, "little")

    Out[7]:

    b'\x11\xdd\xd97\xdbq\x0f\xcfg|t9R\xca\x03Z\x8cj\x10\x0e\x83\xd9W\x03\xa7\xb9\x9f\x91\xfd\xfc\x9a\xe2\xe5\x80u\xd0\xe7\x9fv\x88\xb7W\xf8h\xc7\xdeg\x10\xd7\x8b\xa2u(`u?)\xc1\x06\x82l\x10\xf6R\xcc\x8b\x16\xa6\xda\x8d\xdf\xee\xbfq\xfc\x07`\xb3D\xbaA\x8dzq\x18\xbd\xa8nS8\xe4\x04v?V\xe0,]e\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4120 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:29 · PVG 13:29 · LAX 21:29 · JFK 00:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.