首页 文章

将非常大的基数n转换为字节

提问于
浏览
3

我在 nn 由用户指定)中有一个非常大的数字,存储为一个数组,每个元素代表一个数字 . u[0] 是最高位, u[1] 是第二高位, u[-1] 是最低位,依此类推 . 前导零被理解为没有意义:例如,如果 n 为8,则 [0, 0, 0, 4, 7, 3] 等于 [4, 7, 3] 并且在基数8中等于(473),或者在基数10中为315,或者在十六进制中为 13B ,或者作为字节数组为 [1, 59] .

我想将其转换为一个字节数组,对应于相同数字的base-256表示,最小前导零 . 我有以下代码:

def base_n_to_byte_array(digits, from_base):
    """ Converts a base n number to a byte array.

    :param digits: Digits of the number, starting from highest.
    :param from_base: Base in which the number is given.
    """

    x = 0
    n = len(digits)
    for i in range(0, len(digits)):
        x += digits[i] * int(math.pow(from_base, n - i - 1))

    min_length = max(math.ceil(math.log(x, 256)), 1)
    byte_array = x.to_bytes(min_length, byteorder='big')
    return byte_array

这适用于较小的数字(几百位) . 然而,事实证明 math.pow 是相当有限的,例如,如果我们使用基数8, math.pow(8, 341) 是我能得到的最高功率, math.pow(8,342) 失败了 OverflowError: math range error .

我知道处理大数字的常用方法是将它们表示为浮点数 - 但在这种情况下,我使用此代码将二进制文件编码/解码为替代表示(例如,trytes) . 因此,如果由于精度损失而改变了较不重要的字节,很多数据将被破坏,因此我不能使用近似功率计算 - 我需要结果准确 .

我怎么解决这个问题?是否 math.pow 的版本没有't overflow? Is there a more efficient base conversion algorithm that I'米俯视?

1 回答

  • 4

    是否有一个不会溢出的math.pow版本?

    尝试使用内置的取幂运算符 ** . AFAIK它没有 math.pow 所具有的相同限制 .

    >>> math.pow(8,342)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    OverflowError: math range error
    
    >>> 8**342
    719077253944926363091722076315609893447190791576922629093720324630930703222003852530833909289630144084480455519485573430635159075257666489971389722557896497511071573699461941105208878404984376477812331808340023075352602729369851525895652442163308948653402042738345192959788983753918865219341425318496896548864L
    

相关问题