2015-07-21 37 views
3

我有一個非常大的基數nn由用戶指定),以數組形式存儲,每個元素表示一個數字。 u[0]是最高的數字,u[1]是第二高的,u[-1]是最低的數字等等。前導零被理解爲沒有意義:例如,如果n是8,[0, 0, 0, 4, 7, 3]等於[4, 7, 3],並且它們都等於(473)在基址8中,或者315在基址10中,或者13B以十六進制表示,或者[1, 59]作爲字節數組。將非常大的基數n轉換爲字節

我想將其轉換爲一個字節數組,它對應於相同數字的基數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版本?有沒有更高效的基礎轉換算法,我忽略了?

+0

你需要的是[任意精度算術](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic)。 – WhatsUp

+0

@WhatsUp Python自動執行此操作,只要您避免浮動。 – Teepeemm

+0

@WhatsUp我知道這是我的選擇之一,我正在問如何在Python3中做到這一點。 – Superbest

回答

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 
+1

['math.pow']的文檔(https://docs.python.org/3/library/math.html#math.pow)明確指出'pow'(aka'**')不會具有相同的限制。 – Teepeemm

+1

太棒了!在這種情況下,我放棄了我的「AFAIK」並衷心贊同'pow'和'**'。 – Kevin