Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert from decimal to any base number in Python

This function takes in any base-10 integer and returns the string representation of that number in its specified base-32 form:

def encodeN(n,N,D="0123456789qwertyuiopasdfghjklzxc"):
    return (encodeN(n//N,N)+D[n%N]).lstrip("0") if n>0 else "0"

Example:

print (encodeN(16002,32))

Output:

ya2

But I have a problem with writing a decoding function from base-32 back to base-10. How can I write it? Can I enter custom nonstandard characters to extend the base-n?

like image 237
Tomasz Przemski Avatar asked Mar 07 '23 09:03

Tomasz Przemski


1 Answers

You could cheat:

tmap = str.maketrans('qwertyuiopasdfghjklzxc', 'abcdefghijklmnopqrstuv')
result = int(inputvalue.translate(tmap), 32)

Demo:

>>> tmap = str.maketrans('qwertyuiopasdfghjklzxc', 'abcdefghijklmnopqrstuv')
>>> inputvalue = 'ya2'
>>> int(inputvalue.translate(tmap), 32)
16002

int() is perfectly capable of translating arbitrary bases back to integer values; all you need to do is use the standard progression of letters. The str.translate() call above maps your custom progression to the standard.

Otherwise, take each character from your input string, starting at the left, map that to an integer from your character map, and multiply by the base N each time:

def decodeN(n, N, D={c: i for i, c in enumerate("0123456789qwertyuiopasdfghjklzxc")}):
    result = 0
    for c in n:
        result = (result * N) + D[c]
    return result

This is the slower option; str.translate() and int() both use optimised C code to do their jobs, and will always be faster than a pure-python approach.

Translating that to a recursive version to match your encodeN() implementation:

def decodeN(n, N, D={c: i for i, c in enumerate("0123456789qwertyuiopasdfghjklzxc")}):
    return decodeN(n[:-1], N) * N + D[n[-1]] if n else 0
like image 76
Martijn Pieters Avatar answered Mar 28 '23 14:03

Martijn Pieters