(see also Binary representation of numbers)
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.