Version 1 of Based numbers

Updated 2002-07-08 06:32:27

Richard Suchenwirth 2002-07-06 - Every string standing for a number has to be understood relative to its base. We're most familiar with base 10 (the decimal system), where e.g. 123 stands for

 1*10^2 + 2*10^1 + 3*10^0

and in computery the bases 2 (binary), 8 (octal), and 16 (hexadecimal) are also fairly common, but any integer could function as a base as long as we have enough distinct digits. If you want to experiment with other bases, here are two routines that convert a number to and from a different base, up to 62 (base64 uses a very different sequence of digits, so I didn't go that far)

Note also that signs are preserved (unlike computery habit to have octals and hexadecimals as unsigned, resp. sign-extended):

 proc base {base number} {
    set negative [regexp ^-(.+) $number -> number]
    set digits {0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N
        O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p
        q r s t u v w x y z}
    set res {}
    while {$number} {
        set digit [expr {$number % $base}]
        set res [lindex $digits $digit]$res
        set number [expr {$number / $base}]
    }
    if $negative {set res -$res}
    set res
 }
 proc frombase {base number} {
    set digits {0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N
        O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p
        q r s t u v w x y z}
    set negative [regexp ^-(.+) $number -> number]
    set res 0
    foreach digit [split $number ""] {
        set decimalvalue [lsearch $digits $digit]
        if {$decimalvalue<0 || $decimalvalue >= $base} {
            error "bad digit $decimalvalue for base $base"
        }
        set res [expr {$res*$base + $decimalvalue}]
    }
    if $negative [set res -$res]
    set res
 }

Category Mathematics - Arts and crafts of Tcl-Tk programming