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 - optimized

This is a second iteration on my previous post.

    Seconds for 25,000 Iterations    
Number Base ToBase10 ToBase10-2 Change
1111 2 1.08 0.656 -40%
1523 6 1.09 0.547 -50%
15A23 26 1.86 0.703 -38%

Take the above for what it’s worth.  If this is a time critical conversion and you have tight control over the number being converted – you may opt for using ToBase10-2 and wrapping it in a vl-catch-all-apply.  Either way, it’s your call.

(defun ToBase10-2(NumBase InputValue / )
       (
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
 
)

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.