Converting an integer to a base 2 string

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
}

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```

Here is the output of the demo script, right-justified for expository purposes:

``` 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```

Omar Medina 11-08-2006 Another Variant:

``` #--------------------------
proc pToBinaryStr {vValue} {
set vBinStr ""
foreach vVal [split [format %lX \$vValue] {}] {
switch \$vVal {
0 {append vBinStr "0000"}
1 {append vBinStr "0001"}
2 {append vBinStr "0010"}
3 {append vBinStr "0011"}
4 {append vBinStr "0100"}
5 {append vBinStr "0101"}
6 {append vBinStr "0110"}
7 {append vBinStr "0111"}
8 {append vBinStr "1000"}
9 {append vBinStr "1001"}
a -
A {append vBinStr "1010"}
b -
B {append vBinStr "1011"}
c -
C {append vBinStr "1100"}
d -
D {append vBinStr "1101"}
e -
E {append vBinStr "1110"}
f -
F {append vBinStr "1111"}
}
}
return \$vBinStr
}
#--------------------------```

Output:

``` #--------------------------
pToBinaryStr 45
00101101
pToBinaryStr 4
0100
pToBinaryStr 7777
0001111001100001
pToBinaryStr 0x334
001100110100
#--------------------------```

RS 2006-08-11: Note that the "mysterious reason" mostly is historic: format just wraps C's sprintf() function. Besides that, Tcl, has binary scan and binary format:

``` % binary scan [binary format I 3] B* bits; set bits
00000000000000000000000000000011
% binary scan [binary format I -3] B* bits; set bits
11111111111111111111111111111101```

So it's just the intended length of the bitstring that you'll have to manipulate, if you so wish :^)

RS 2006-10-04: Hex string of arbitrary length to bits:

``` interp alias {} hex2bin {} string map -nocase {
0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111
8 1000 9 1001 a 1010 b 1011 c 1100 d 1101 e 1110 f 1111
}```

ferrieux 8.6 has %b, %lb, %llb in format.

 Category Mathematics Category Binary Data