Convert very large base number n to bytes

I have a very large number in a database n

( n

user supplied) stored as an array with each element representing a digit. u[0]

- the highest digit, u[1]

- the second largest, u[-1]

- the least significant digit, and so on. Leading zeros are understood to be meaningless: for example, if n

is 8, it is [0, 0, 0, 4, 7, 3]

equivalent [4, 7, 3]

and both are (473) in base 8 or 315 in base 10, either 13B

in hexadecimal, or [1, 59]

as a byte array.

I want to convert this to an array of bytes that match the base-256 representation of the same number with minimal leading zeros. I have the following code:

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

      

This works for smaller numbers (several hundred digits). However, it turns out to be math.pow

quite limited, for example if we use base 8 math.pow(8, 341)

is the highest cardinality I can get while math.pow(8,342)

failing with OverflowError: math range error

.

I know that the general way to work with large numbers is to represent them as floating points, but in this case, I use this code to encode / decode binaries into alternate representations (like trytes). Therefore, if less significant bytes change due to loss of precision, most of the data will be corrupted, so I cannot use a rough calculation of the cardinality - I need the result to be accurate.

How can I solve this problem? Is there a version math.pow

that doesn't overflow? Is there a better database conversion algorithm that I am overlooking?

+3


source to share


1 answer


Is there a version math.pow

that doesn't overflow?

Try using the built-in exponent operator **

. AFAIK doesn't have the same limitations as math.pow

.



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

>>> 8**342
719077253944926363091722076315609893447190791576922629093720324630930703222003852530833909289630144084480455519485573430635159075257666489971389722557896497511071573699461941105208878404984376477812331808340023075352602729369851525895652442163308948653402042738345192959788983753918865219341425318496896548864L

      

+4


source







All Articles