Version 0 of base conversion

Updated 2006-07-17 16:35:51

A general base-conversion procedure for arbitrary length string representations of numbers with integer and/or fraction.

 #=============================================================================
 # PROC    : baseconvert
 # PURPOSE : convert number in one base to another base
 # AUTHOR  : Richard Booth
 # DATE    : Fri Jul 14 10:40:50 EDT 2006
 # ---------------------------------------------------------------------------
 # ARGUMENTS :
 #   % base_from
 #       original base (expressed in base 10)
 #   % base_to
 #       base to convert number to (expressed in base 10)
 #   % number
 #       number expressed in base_from (must have form int.fra, int, or .fra)
 # RESULTS :
 #   * returns number expressed in base_to
 # EXAMPLE-CALL :
 #{
 #  set num16 [baseconvert 10 16 3.1415926535]
 #}
 #=============================================================================
 proc baseconvert {base_from base_to number} {
     set number [string tolower $number]
     if {![regexp {([0-9a-z]*)\.?([0-9a-z]*)} $number match sint sfra]} {
         puts "baseconvert error: number \"$number\" is not in correct format"
         return ""
     }
     set map 0123456789abcdefghijklmnopqrstuvwxyz
     set i -1
     foreach c [split $map ""] {
         incr i
         set D2I($c) $i
         set I2D($i) $c
     }
     set lint [string length $sint]
     set lfra [string length $sfra]
     set converted_number 0
     if {$lint > 0} {
         set i -1
         foreach c [split $sint ""] {
             set B([incr i]) $D2I($c)
         }
         set aint ""
         while {1} {
             set s 0
             set r 0
             for {set i 0} {$i < $lint} {incr i} {
                 set v [expr $B($i) + $r*$base_from]
                 set B($i) [expr int($v/$base_to)]
                 set r [expr $v - $base_to*$B($i)]
                 set s [expr $s + $B($i)]
             }
             set aint "$I2D($r)$aint"
             if {$s == 0} {break}
         }
         set converted_number $aint
     }
     if {$lfra > 0} {
         set s [expr $lfra*int(1.0*log($base_from)/log($base_to))]
         set i $lfra
         foreach c [split $sfra ""] {
             set B([incr i -1]) $D2I($c)
         }
         set afra ""
         for {set j 0} {$j < $s} {incr j} {
             set r 0
             for {set i 0} {$i < $lfra} {incr i} {
                 set v [expr $base_to*$B($i) + $r]
                 set r [expr int($v/$base_from)]
                 set B($i) [expr $v - $r*$base_from]
             }
             set afra "$I2D($r)$afra"
         }
         append converted_number .$afra
     }
     return $converted_number
 }

a small test script for baseconvert:

 set fmt "%-10s (base %-2d)  =>  %-10s (base %-2d)"
 foreach number {12ff.abb 122. 125 .222 0.222 0.22 0.2 0.1} {
    puts [format $fmt $number 16 [baseconvert 16 10 $number] 10]
    puts [format $fmt $number 16 [baseconvert 16 8  $number] 8]
    puts [format $fmt $number 16 [baseconvert 16 2  $number] 2]
 }

CATEGORY ALGORITHM