[Tutor] RE: Base converter bases 2-62

cino hilliard hillcino368@hotmail.com
Fri Jun 20 05:01:01 2003


Thanks Jeff and others


Lotta good stuff here
I asked for this. Thanks. Improvements are welcome.

The org code in BCX

!#define   ascii(Q) ((Q < 10) ? (Q+=48) : (Q+=55))
!#define decimal(Q) (Q < 58) ? (Q-=48) : (Q-=55)
const maxx = 10^16

function r2r$(r1 as double,r2 as double,num$)
dim J,RDX$,Q#, PWR,zeros$,tmp$
dim temp#,dec#,ln,j,RDX2$,asci,ascii2
dec# = 0                              'CLEAR TO ALLOW LOOP INPUT PER BASE
ln  = len(num$)                       'PARSE THE INPUT STRING AND
for j = 1 TO ln                       'GET HEX DIGITS OF HEX NUMBER
RDX2$  = MID$(num$,j,1)
asci = ASC(RDX2$)                    'GET ASCII CODE OF HEX DIGIT
temp# = r2^(ln-j)                     'COMPUTE POWERS OF RADIX
if temp# > maxx then
function = "overflow"
end if
ascii2 = decimal(asci)
dec# += ascii2*temp#                  'MULTIPLY BY DEC VALUE POINTED TO BY
if dec# > maxx then                   'THE ASCII CODE IN H[48-57] AND 
H[65-70]
function =  "overflow"
end if
next j
RDX$ = ""
PWR    = LOG(dec#)/LOG(r1)            'GET MAX POWER OF BASE
FOR J  = PWR TO 0 STEP - 1            'DIVIDE BY DESCENDING POWERS OF RADIX 
to
Q      = dec#/r1^J               'GET ASC VALUE
dec#   = mod(dec#,r1^J)
tmp$ = chr$(ascii(Q))
RDX$   = RDX$ & tmp$                  'CONCATANATE OUTPUT RADIX STRINGS
NEXT J
zeros$ = repeat$(8-len(RDX$),"0")
if r1 = 2 then RDX$ = zeros$ & RDX$
function = TRIM$(RDX$)                        'RETURN RADIX STRING
end function
I left zero fill out but python has a neat function that will do this.

The first rule of translation is to try to duplicate as much as possible to 
maintain the flow.
Then when it works, give it hell in improvement.See more comments below.


>From: "Jeff Shannon" <jeff@ccvcorp.com>
>To: tutor@python.org
>CC: cino hilliard <hillcino368@hotmail.com>
>Subject: Re: [Tutor] RE: Base converter bases 2-62
>Date: Thu, 19 Jun 2003 17:45:39 -0700
>
>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.
True
>
>>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.
Yes I had planned to do this. The while was a quick trial to keep my head 
straight by not
having to unravel for errors

for j = 1 TO ln                       'GET HEX DIGITS OF HEX NUMBER
RDX2$  = MID$(num$,j,1)
asci = ASC(RDX2$)                    'GET ASCII CODE OF HEX DIGIT

>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.
This is good stuff!
>
>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,

This is not correct. The base of the numerical syntaxof most languages  is 
10 or decimal.
a basic integer,c integer,python integer,SAS integer, Cobol, Fourth, etc is 
decimal unless otherwise specified. some assembly languages assume hex. But 
that is clarified up front.


>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.
This I agree with in python.  I did this origionally because I added this 
function into the BCX basic to C
translator code to be callable from the bcx language. We want to use the 
intrinsic functions as much as
possible in the construction of and implementation of new functions reducing 
dangling arrays out there.
Other good reasons for this method described below.
>
>As Magnus mentioned, this can all be done with a string.
>
> >>> digits = 
>"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
> >>> digits.index('F')
>15
Yeah, the very first program did it this way. Other factors (above) were 
considered to use the ascii
table such as using the entire ascii set from 32 to 255 for a super base 
converter. This would make the
code easier to maintain when you wanted to add more bases. And of course the 
main reason. What
if I use This fancy dan code above and a letter is missing or in reverse or 
whatb ever.

Also if I am not mechanically concatenating the string such as in most 
basics (BCX uses & for concat - DUMB but it currently has to because of C).

digits$ = ""
for j=32 to 255
digits$ = digits$ + chr$(j)
next j
Now I have an  exact table that I can use.
Python can do this
Another factor may be speed (in my going back to TRS80 model I mind). I 
think that function call
is much faster than an array lookup. It becomes a matter of taste. We are 
different. I will try
this.
> >>>
>
>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....
Why even mention this? I went to all this trouble for base 32 max? the atol 
and ltoa in c do this
for you to base 36.
>
>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:
Excellent
>
>>    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
>
Good work Jeff.
I will take your suggestions and see if I can come up with a prototype (with 
your guys
help of course) to be a candidate fo inclusion into the language. Well, 
maybe a package
in my little o'l  library.

The next step will be to take this to output in a list eg.,
>>>convert.base(10,16,2^16-1) = [15,15,15,15] = FFFF hex. This will allow 
>>>arbitrary base size.
Hey, This may be our passport to destiny. We do a 
convert.base(10,1000,2^512-1) and pick
our  lottery numbers from the 52 entries in the list 
[95,85,6,649,433,...407,13].

Cheers and Roebuck

  3         3        3         3        3        6            2              
  (0^0)
2   +  13  +  33  +  43  =  49   =  7    =  343   = 117649

_________________________________________________________________
STOP MORE SPAM with the new MSN 8 and get 2 months FREE*  
http://join.msn.com/?page=features/junkmail