Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manipulate and represent binary numbers in C++

Tags:

c++

binary

I'm currently trying to build a lookup table for a huffman tree using a pretty simple preorder traversal algorithm, but I'm getting stuck carrying out very basic bit wise operations. The psuedo code follows:

void preOrder(huffNode *node, int bit) //not sure how to represent bit
{
  if (node == NULL)
    return;

  (1) bit = bit + 0; //I basically want to add a 0 onto this number (01 would go to 010)
  preOrder(node->getLeft(), bit);
  (2) bit = bit - 0 + 1; //This should subtract the last 0 and add a 1 (010 would go to 011)
  preOrder(node->getRight());


}

I'm getting quite confused about how to carry out the operations defined on lines (1) and (2)

What data type type does one use to represent and print binary numbers? In the above example I have the number represented as an int, but i'm pretty sure that that is incorrect. Also how do you add or subtract values? I understand how & and | types logic works, but I'm getting confused as to how one carries out these sorts of operations in code.

Could anyone post some very simple examples?

like image 659
Wakka Wakka Wakka Avatar asked Jul 30 '12 00:07

Wakka Wakka Wakka


2 Answers

Here's some basic examples of binary operations. I've used mostly in-place operations here.

int bit = 0x02;   //               0010
bit |= 1;         // OR  0001 ->   0011
bit ^= 1;         // XOR 0001 ->   0010
bit ^= 7;         // XOR 0111 ->   0101
bit &= 14;        // AND 1110 ->   0100
bit <<= 1;        // LSHIFT 1 ->   1000
bit >>= 2;        // RSHIFT 2 ->   0010
bit = ~bit;       // COMPLEMENT -> 1101

If you want to print a binary number you need to do it yourself... Here's one slightly inefficient, but moderately readable, way to do it:

char bitstr[33] = {0};
for( int b = 0; b < 32; b++ ) {
    if( bit & (1 << (31-b)) )
        bitstr[b] = '1';
    else
        bitstr[b] = '0';
}
printf( "%s\n", bitstr );

[edit] If I wanted faster code, I might pre-generate (or hardcode) a lookup table with the 8-bit sequences for all numbers from 0-255.

// This turns a 32-bit integer into a binary string.
char lookup[256][9] = {
    "00000000",
    "00000001",
    "00000010",
    "00000011",
    // ... etc (you don't want to do this by hand)
    "11111111"
};

char * lolo = lookup[val & 0xff];
char * lohi = lookup[(val>>8) & 0xff];
char * hilo = lookup[(val>>16) & 0xff];
char * hihi = lookup[(val>>24) & 0xff];

// This part is maybe a bit lazy =)
char bitstr[33];
sprintf( "%s%s%s%s", hihi, hilo, lohi, lolo );

Instead, you could do this:

char *bits = bitstr;
while( *hihi ) *bits++ = *hihi++;
while( *hilo ) *bits++ = *hilo++;
while( *lohi ) *bits++ = *lohi++;
while( *lolo ) *bits++ = *lolo++;
*bits = 0;

Or just unroll the whole thing. ;-)

char bitstr[33] = {
    hihi[0], hihi[1], hihi[2], hihi[3], hihi[4], hihi[5], hihi[6], hihi[7],
    hilo[0], hilo[1], hilo[2], hilo[3], hilo[4], hilo[5], hilo[6], hilo[7],
    lohi[0], lohi[1], lohi[2], lohi[3], lohi[4], lohi[5], lohi[6], lohi[7],
    lolo[0], lolo[1], lolo[2], lolo[3], lolo[4], lolo[5], lolo[6], lolo[7],
    0 };

Of course, those 8 bytes in the lookup are the same length as a 64-bit integer... So what about this? Much faster than all that pointless meandering through character arrays.

char bitstr[33];
__int64 * intbits = (__int64*)bitstr;
intbits[0] = *(__int64*)lookup[(val >> 24) & 0xff];
intbits[1] = *(__int64*)lookup[(val >> 16) & 0xff];
intbits[2] = *(__int64*)lookup[(val >> 8) & 0xff];
intbits[3] = *(__int64*)lookup[val & 0xff];
bitstr[32] = 0;

Naturally, in the above code you would represent your lookup values as int64 instead of strings.

Anyway, just pointing out that you can write it however is appropriate for your purposes. If you need to optimize, things get fun, but for most practical applications such optimizations are negligible or pointless.

like image 106
paddy Avatar answered Oct 04 '22 05:10

paddy


Unless your binary sequences will get longer than the number of bits in an int, you can just use an int.

To add a 0 to the end of the current representation of a, you can use a << 1

To replace a 0 at the end of the current representation of a with a 1, you can use a ^= 1

Note that to use an int in this way, you will also need to keep track of where in the int your bits start, so that if you have e.g., the value 0x0, you can know which of 0, 00, 000, ... it is.

like image 34
David Avatar answered Oct 04 '22 04:10

David