[Tutor] RE: Base converter bases 2-62

Jeff Shannon jeff@ccvcorp.com
Thu Jun 19 20:46:03 2003


cino hilliard wrote:

> Question. How can I get convert.base(r1,r2,str) without having to type 
> the quotes for the st?
> Eg., convert.base(16,10,FFFF) instead of convert.base(16,10,"FFFF") = 
> 65535 ? This is required only if out of 0 - 9 range. 
> convert(16,10,255) = FF works fine
>
> Jeff Shannon attempted to answer this with no. I am not convinced it 
> cannot be done. In dos the command tail can be mixed and python should 
> be able to read convert.base(16,10,FFFF). I will figure it out and 
> post later. I may have to got the route
> import sys
> r1 = long(sys.argv[1])   #convert the first argument in the command 
> tail to long
> r1 = long(sys.argv[2])   #convert the second argument in the command 
> tail to long
> num = str(sys.argv[3])   #convert the third argument in the command 
> tail to string
> Can't is not in my vocabulary. :-) 


Ah, but arguments to a script (parsed by the OS) are an entirely 
different matter from arguments to a function (parsed by the Python 
interpreter).  Clearly you can write a script that'll do that -- indeed, 
it would probably take extra effort to allow quotes around a script 
parameter.  But parsing a single command line is an entirely separate 
(and much simpler) problem than parsing an entire sourcefile, which may 
contain arbitrary variable names and multi-line statements.

> def base(r1,r2,num):            #convert the string in base r1 to  a 
> string in base r2
>    import math                    #we need this to get the power  of
>    num = str(num)
>    dec = 0                          #Clear to allow loop input per  base
>    ln  = len(num)                 #save length of string to convert 
> for later parsing
>    j=0
>    while j < ln:                     #parse the input string
>        asci = ord(num[j])        #Get the ascii code of the char in 
> string to convert
>        temp   = r1**(ln-j-1)    #Compute the powers of the radix to 
> convert from
>        ascii2 = decimal(asci)     #Get the decimal value of the  ascii 
> code
>        dec += ascii2*temp      #Multiply by decimal value and  power 
> of radix
>        j+=1 


Instead of using this awkward while loop, why not use a for loop?  That 
way you don't need to worry about tracking your index variable.

for j in range(ln):
    asci = ord(num[j])
    temp = r1 ** (ln - j - 1)
    ascii2 = decimal(asci)
    dec += ascii2*temp

You can do the same sort of thing with your other loop, using 
range(int(PWR),-1,-1) to step backwards.

Now, as to your decimal() and ascii() functions...

First, as I described in my other email, "decimal" isn't really an 
appropriate name since the integer you return doesn't really have a base 
(only representations of it do).  More importantly, though, your if/else 
and addition is very unclear.  One would practically need to have an 
ASCII chart in hand to try to figure out what you're up to.

As Magnus mentioned, this can all be done with a string.

 >>> digits = 
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
 >>> digits.index('F')
15
 >>>

I can easily convert a character into an integer this way.  Once you 
have the digits string defined (at the top of your module, presumably), 
you can replace any call to decimal(ord(char)) with a call to 
digits.index(char).  So now I can rewrite that loop like this:

for j in range(ln):
    temp = r1 ** (ln - j - 1)
    value = digits.index(num[j])
    dec += value*temp

(Of course, as Magnus pointed out, this whole loop can be easily 
replaced with 'dec = int(num, r1)' as long as you can cope with a 
maximum base of 32....)

The reverse is even easier -- given an integer value, I can get the 
appropriate character to represent it simply by indexing into the string:

 >>> digits[15]
'F'
 >>>

In your second loop, I see that you're using two separate operations to 
get the dividend and the remainder.  This can be done in a single 
operation using the divmod() built-in function.  So with these pieces in 
mind, I can rewrite this:

>    j = int(PWR)
>    while j >= 0:                                    #Divide by 
> descending  powers of the radix to
>        Q   = dec/(r2**j)                          #get the ascii values
>        dec = dec%(r2**j)                       #get the remainder of 
> divison for next division
>        tmp = chr(ascii(Q))
>        RDX = RDX + tmp                         #Concatenate the output 
> string
>        j-=1 


into this:

for j in range(int(PWR), -1, -1):
    Q, dec = divmod(dec, (r2**j))
    RDX += digits[Q]

Jeff Shannon
Technician/Programmer
Credit International