Un1
Un1

Reputation: 4132

How to convert a string of arbitrary base back to decimal?

I'm trying to convert a decimal number to an arbitrary base and back to decimal. I found this code below from another question:

def int2base(x,b,alphabet='0123456789abcdefghijklmnopqrstuvwxyz'):
    'convert an integer to its string representation in a given base'
    if b<2 or b>len(alphabet):
        if b==64: # assume base64 rather than raise error
            alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
        else:
            raise AssertionError("int2base base out of range")
    if isinstance(x,complex): # return a tuple
        return ( int2base(x.real,b,alphabet) , int2base(x.imag,b,alphabet) )
    if x<=0:
        if x==0:
            return alphabet[0]
        else:
            return  '-' + int2base(-x,b,alphabet)
    # else x is non-negative real
    rets=''
    while x>0:
        x,idx = divmod(x,b)
        rets = alphabet[idx] + rets
    return rets

When I convert a decimal to hex:

in_base16 = int2base(number, 16)

it works, but when I try to convert that result back to decimal (base 10):

back_to_10 = int2base(in_base16, 10)

... it gives me the error:

    if x<=0:
    TypeError: '<=' not supported between instances of 'str' and 'int'

It can't convert a string back to a number for some reason. I don't understand why. How would I convert a number of an arbitrary base back to decimal?

Upvotes: 4

Views: 1382

Answers (4)

thebjorn
thebjorn

Reputation: 27311

You'll need one function for converting from int to base (returning a string that represents a number in that base -- here up to base 36):

digits = '0123456789abcdefghijklmnopqrstuvwxyz'

def int2base(n, b=2, digits=digits):
    "convert integer n to base b"
    if n < 0:
        raise ValueError("no negative numbers")
    if n < b:
        return digits[n]
    res = []
    q = n
    while q:
        q, r = divmod(q, b)
        res.append(digits[r])
    return ''.join(reversed(res))

and another function for converting back from base to int:

def base2int(s, base=2, digits=digits):
    "convert string s representing a number in base to int (base 10)"
    if not (2 <= base <= len(digits)):
        raise ValueError("base must be >= 2 and <= %d" % len(digits))
    res = 0
    for i, v in enumerate(reversed(s)):
        digit = digits.index(v)
        res += digit * (base ** i)
    return res

Upvotes: 2

Prune
Prune

Reputation: 77827

Your basic problem is the signature: your function works only on x as an integer. Instead, you need either a second function that works on strings, or a type check at the top of this routine to detect the input type.

The basic problem is that you've assumed that you can get the digit's value within the radix (base) with a simple reference; this works for an integer, but not a string. "9" doesn't yield a numeric value of 9; "B" doesn't give you 11.

Instead, you need to feed the character to the index function and take the return value:

digit_value = alphabet.index(char)

will give you the character's position in the alphabet, which is the digital value you want for your computations.

Can you take it from there?

Upvotes: 1

Vin&#237;cius Figueiredo
Vin&#237;cius Figueiredo

Reputation: 6508

If base-n is up to 36, you can use the built-in int(str,base).

>>> int('AA', 32)
330

Upvotes: 2

Random Davis
Random Davis

Reputation: 6857

Your int2base function only accepts an integer as input, so you need to convert your string to an integer. So, you can simply use the built-in function int(string, base) to do this:

in_base16 = int2base(number, 16)
back_to_10 = int2base(int(in_base16, 16), 10)

Which works fine.

Upvotes: 1

Related Questions