I hate doing things I can make my computer do for me. My adventures in customizing and automating computers. Primarily with AutoCAD and Microsoft Office.

Monday, May 25, 2009

Number base conversion

This routine will convert a number from any base between 2 and 36, inclusive, to base 10.

  Routine:    ToBase10
  Purpose:    Convert a number from any base between 2 and 36 to base 10
  Arguments:    NumBase - integer where 2<= NumBase <= 36.  The number base from which we are
            converting.
          InputValue
            Symbol - example: '010010
            Number - example:   10010
            string - example: "010010" or "10010"
  Returns:    The input value converted to base 10
=============================================================================================
  This routine is the inverse of the base routine found in the acad developement help files
    under "ASCII Code Conversion", hence, (tobase10 16 (base 16 5284)) returns 5284
---------------------------------------------------------------------------------------------
  Example1:    (tobase10 2 '11001011 )  returns      203
  Example2:     (tobase10 2  11001011 )  returns      203
  Example3:     (tobase10 2 "11001011")  returns      203

  Example4:     (tobase10 6 '15243 )     returns     2475
  Example5:     (tobase10 6  15243 )     returns     2475
  Example6:     (tobase10 6 "15243")     returns     2475

  Example7:     (tobase10 16 '34F1A )    returns   216858
  Example9:     (tobase10 16 "34F1A")    returns   216858
    Notice that '34F1A cannot be represented as a number, hence, only two examples

  Example10:    (tobase10 36 '11001011 ) returns 60525828
  Example11:    (tobase10 36  11001011 ) returns 60525828
  Example12:    (tobase10 36 "11001011") returns 60525828
    As a check, use this online java applet.

 

(defun ToBase10 (NumBase InputValue / rtval)

;;Here we convert out input value’s type.
  (
cond
   
((= 'str (type inputvalue))
     (
setq inputvalue (strcase inputvalue))
     )
    ((
= 'SYM (type inputvalue))
     (
setq InputValue (vl-symbol-name InputValue))
     )
    )

;;Here we start validating our input
  (
cond
   
;;Base is not an integer
    ((not (= 'int (type NumBase)))
     (
strcat
      
"ERROR|ToBase10 base argument must be an integer - "
      
(vl-prin1-to-string (type NumBase))
      
" provided (" (vl-prin1-to-string NumBase) ")"
      
)
     )
   
;;Base argument is out of range
    ((or
      
(> 2 NumBase)
       (
< 36 NumBase)
       )
     (
strcat
      
"ERROR|ToBase10 Base argument must be greater than 1 and less than 36 - " (itoa NumBase) " provided."
      
)
     )
   
;;InputValue is of wrong type for specified base
    ((and
      
(> NumBase 10)
       (
not (= 'STR (type InputValue)))
       )
      
"ERROR|Numbers in a base greater than 10 must be expressed as a string - ToBase routine."
   
)
   
;;InputValue has invalid characters
    ((not (vl-every
       
(function
         
(lambda (asciicode)
        (
cond
         
;;Character below "0" used
          ((< asciicode 48) nil)
         
;;Character greater than valid used for base less than or equal to 10
          ((and
            
(<= NumBase 10)
             (
> asciicode (+ 47 NumBase))
             )
          
nil
          
)
         
;;For base greater than 10, invalid character used
          ((and (> NumBase 10)
            (
not (wcmatch (chr asciicode) (strcat "[0-9],[A-" (chr (+ NumBase 54)) "]")))
            )
          
nil
          
)
          (
T T)
          )
        )
          )       
        (
vl-string->list (if (= 'INT (type InputValue))
                   (
itoa InputValue)
                  
InputValue
                  
)
          )
      )
     )
     (
strcat
      
"ERROR|Invalid InputValue argument provided to ToBase10 routine : " (vl-prin1-to-string InputValue)
     )
    )

;;Now we’re done validating the input, let’s get started
    (
T
    
(setq
      
indx      0
      
;;Get the list of multipliers
       temp (mapcar
         
(function
       
(lambda    (x)
          (
if (< 57 x)
            (
- x 55)
            (
- x 48)
          )
        )
          )
          (
reverse (vl-string->list
            
(if (= 'INT (type InputValue))
               (
itoa InputValue)
              
InputValue
            
)
               )
          )
        )
      
rtval      0
    
)
     (
repeat (length temp)
       (
setq
    
digit (nth indx temp)
    
rtval (+ rtval (* Digit (expt NumBase indx)))
    
indx  (1+ indx)
       )
     )
    
rtval
   
)
  )
)

The concept for this approach was derived from here - chapter IX.

No comments: