Version 4 of Converting an integer to a base 2 string

Updated 2006-03-12 22:07:39

WJP For mysterious reasons format will print an integer in decimal, hex, or octal, but not binary. Here's a procedure that does. It works for negative integers as well as positive. If the argument is not an integer it throws an exception. It will use a sufficient number of bits regardless of the size of the integer. It takes an optional second argument specifying the number of bits to use. If the required number of bits is larger, this value is ignored. If the specified number of bits is larger than the necessary number of bits, the result is zero-padded to the specified number of bits.

 proc binfmt1 {k {cnt 8}} {
    if {![string is integer $k]} {error "argument is not an integer"}
    #Compute minimum number of bits necessary
    #This is the integer ceiling of the log of the number to the base 2.
    if {$k == 0} {set bits 1} else {set bits [expr int(ceil((log(abs($k)))/(log(2))))]}
    if {$bits > $cnt} {set cnt $bits}
    #Now compute binary representation
    for {set i [expr $cnt -1]} {$i > -1} {incr i -1} {
        append s [expr ($k >> $i) & 1]
    }
    return $s
 }

The above version shows how the conversion is done, by shifting and masking. It is almost five times faster to use binary scan to do the actual conversion:

 proc binfmt2 {k {cnt 8}} {
    if {![string is integer $k]} {error "argument is not an integer"}
    #Compute minimum number of bits necessary
    #This is the integer ceiling of the log of the number to the base 2.
    if {$k == 0} {set bits 1} else {set bits [expr int(ceil((log(abs($k)))/(log(2))))]}
    if {$bits > $cnt} {set cnt $bits}
    #Now compute binary representation
    binary scan $k [format "B%d" $cnt] s
    return $s
 }


 proc demo {} {
    puts "binfmt 3         = [binfmt 3]"
    puts "binfmt -3        = [binfmt -3]"
    puts "binfmt 3 0       = [binfmt 3 0]"
    puts "binfmt 3 4       = [binfmt 3 4]"
    puts "binfmt 25        = [binfmt 25]"
    puts "binfmt 1025      = [binfmt 1025]"
    puts "binfmt 69125     = [binfmt 69125]"
    puts "binfmt 69125 24  = [binfmt 69125 24]"
 }

 demo

if {0} { Here is the output of the demo script:

 binfmt 3         = 00000011
 binfmt -3        = 11111101
 binfmt 3 0       = 11
 binfmt 3 4       = 0011
 binfmt 25        = 00011001
 binfmt 1025      = 10000000001
 binfmt 69125     = 10000111000000101
 binfmt 69125 24  = 000000010000111000000101

}