See Also: [Converting an integer to a base 2 string], [Binary representation of numbers], [Based numbers] ---- A general base-conversion procedure for arbitrary length string representations of numbers with integer and/or fraction. [rvb] #============================================================================= # 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] } ---- [rvb] A related problem is sampling a multi-dimensional grid. ''[Lars H]: Hmm... That's a rather antiquated way to do it, though. If you really want all points in the grid, then it is easier to construct it as the [Cartesian product of a list of lists].'' #============================================================================= # PROC : gridsample # PURPOSE : uniformly sample a normalized hypercube # AUTHOR : Richard Booth # DATE : Tue Jul 18 11:19:10 EDT 2006 # --------------------------------------------------------------------------- # ARGUMENTS : # % ndiv # number of divisions of the normalized hypercube # (each independent variable range is [-1, 1]) # % nind # number of independent variables # RESULTS : # * returns list of (normalized) samples # EXAMPLE-CALL : #{ # set samples [gridsample 5 2] #} #============================================================================= proc gridsample {ndiv nind} { if {$nind < 1 || $ndiv < 1} { return {} } set samples {} set base [expr $ndiv+1] set npts [expr pow($base, $nind)] for {set i 0} {$i < $npts} {incr i} { set sample {} set v $i for {set j 0} {$j < $nind} {incr j} { set w [expr int($v/$base)] set r [expr $v - $base*$w] set v $w lappend sample [expr {2.0*$r/$ndiv-1}] } lappend samples [join $sample] } return $samples } a test script for gridsample: set nind 3 set ndiv 6 set samples [gridsample $ndiv $nind] puts "sample A B C" set iexpt -1 foreach sample $samples { puts "[incr iexpt] [join $sample]" } ---- [Category Algorithm] | [Category Mathematics]