小编典典

是否有更快的方法将任意大整数转换为大字节序字节序列?

python

我有以下Python代码可以做到这一点:

from struct import pack as _pack

def packl(lnum, pad = 1):
    if lnum < 0:
        raise RangeError("Cannot use packl to convert a negative integer "
                         "to a string.")
    count = 0
    l = []
    while lnum > 0:
        l.append(lnum & 0xffffffffffffffffL)
        count += 1
        lnum >>= 64
    if count <= 0:
        return '\0' * pad
    elif pad >= 8:
        lens = 8 * count % pad
        pad = ((lens != 0) and (pad - lens)) or 0
        l.append('>' + 'x' * pad + 'Q' * count)
        l.reverse()
        return _pack(*l)
    else:
        l.append('>' + 'Q' * count)
        l.reverse()
        s = _pack(*l).lstrip('\0')
        lens = len(s)
        if (lens % pad) != 0:
            return '\0' * (pad - lens % pad) + s
        else:
            return s

这大约需要174个usec才能转换2**9700 - 1为我的计算机上的字节字符串。如果我愿意使用特定于Python 2.7和Python
3.x的bit_length方法,可以通过l在开始时就将数组预先分配为恰好正确的大小并使用l[something] =语法而不是来将其缩短到159个usecs l.append

我有什么可以做的更快?这将用于转换密码术中使用的大质数以及一些(但不是很多)较小的数。

编辑

目前,这是Python <3.2中最快的选项,任一方向花费的时间大约是接受答案的一半:

def packl(lnum, padmultiple=1):
    """Packs the lnum (which must be convertable to a long) into a
       byte string 0 padded to a multiple of padmultiple bytes in size. 0
       means no padding whatsoever, so that packing 0 result in an empty
       string.  The resulting byte string is the big-endian two's
       complement representation of the passed in long."""

    if lnum == 0:
        return b'\0' * padmultiple
    elif lnum < 0:
        raise ValueError("Can only convert non-negative numbers.")
    s = hex(lnum)[2:]
    s = s.rstrip('L')
    if len(s) & 1:
        s = '0' + s
    s = binascii.unhexlify(s)
    if (padmultiple != 1) and (padmultiple != 0):
        filled_so_far = len(s) % padmultiple
        if filled_so_far != 0:
            s = b'\0' * (padmultiple - filled_so_far) + s
    return s

def unpackl(bytestr):
    """Treats a byte string as a sequence of base 256 digits
    representing an unsigned integer in big-endian format and converts
    that representation into a Python integer."""

    return int(binascii.hexlify(bytestr), 16) if len(bytestr) > 0 else 0

在Python 3.2中,int该类具有to_bytesfrom_bytes函数,它们可以 上述方法更快地完成此任务。


阅读 247

收藏
2020-12-20

共1个答案

小编典典

为了完整性和将来读者对该问题的了解:

从Python
3.2开始,提供了一些函数int.from_bytes()int.to_bytes()这些函数可以按字节顺序选择在bytesint对象之间进行转换。

2020-12-20