[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