A general base-conversion procedure for arbitrary length string representations of numbers with integer and/or fraction. [Richard Booth] #============================================================================= # 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]