So
here's normal, base-1 counting on your fingers. In base 1, you
just raise the number of fingers equal to the value you're trying to
represent:
|
|
This is funky base-2 counting on your fingers. Each finger represents a
different value now, so you have to start counting with '1' at your
pinky, then '2' with just your ring finger, and '3=2+1' is pinky and
ring finger together. '4' is a single raised middle finger. Then
'5=4+1' is middle finger and pinky, and so on. Just 10 digits actually
allows you to count all the way to 1023, but we'll ignore the thumbs
and just use 8 fingers, to count up to 255=128+64+32+16 (left hand
palm-up, pinky is 16) +8+4+2+1 (right hand palm-down, pinky is 1).
This is actually somewhat useful for counting--try it! (Note: the numbers four, sixty-four, and especially sixty-eight should not be prominently displayed. Digital binary counting is not recommended in a gang-infested area.) |
long x=1024;Why? The real answer is 4 billion (and change), which requires 33 bits: a 1 followed by 32 zero bits. But on a 32-bit machine, all you get is the zeros; the higher bits "overflow" and (at least in C/C++) are lost! Understanding the bits underneath your familiar integers can help you understand errors like this one. (Plus, by writing assembly code, you can actually recover the high-order bits after a multiplication if you need them.)
long y=x*x*x*4;
return y;
As Ints |
As Bits |
3<<0 == 3 |
0011<<0 == 0011 |
3<<1 == 6 |
0011<<1 == 0110 |
3<<2 == 12 |
0011<<2 == 1100 |
As Ints |
As Bits |
3>>0 == 3 |
0011>>0 == 0011 |
3>>1 == 1 |
0011>>1 == 0001 |
3>>2 == 0 |
0011>>2 == 0000 |
6>>1 == 3 |
0110>>1 == 0011 |
As Ints |
As Bits |
3&5 == 1 |
0011&0101 == 0001 |
3&6 == 2 |
0011&0110 == 0010 |
3&4 == 0 |
0011&0100 == 0000 |
As Ints |
As Bits |
3|0 == 3 |
0011|0000 == 0011 |
3|3 == 3 |
0011|0011 == 0011 |
1|4 == 5 |
0001|0100 == 0101 |
As Ints |
As Bits |
3^5 == 6 |
0011&0101 == 0110 |
3^6 == 5 |
0011&0110 == 0101 |
3^4 == 7 |
0011&0100 == 0111 |
As Ints |
As Bits |
~0 == big value |
~...0000 == ...1111 |
enum {n=1}; // Number of integers in our tables (== size of internet / 32)The same bitwise testing idea shows up in the "region codes" of Cohen-Sutherland clipping, used in computer graphics.
unsigned int funky_table[n]={(1<<24)|(1<<17)|(1<<12)|(1<<4)};
unsigned int aardvark_table[n]={(1<<31)|(1<<24)|(1<<15)|(1<<6)|(1<<4)};
/* Match up the bits of these two tables using bitwise operations */
void both_tables(const unsigned int *a,const unsigned int *b,unsigned int *o) {
for (int i=0;i<n;i++) o[i]=a[i]&b[i]; /* bitwise AND */
}
/* Match up the bits of these two tables using logical (one-bit) operations */
void both_tables_logical(const unsigned int *a,const unsigned int *b,unsigned int *o)
{
for (int i=0;i<n;i++) {
o[i]=0;
for (int bit=0;bit<32;bit++)
{
unsigned int a_bit=a[i]&(1<<bit);
unsigned int b_bit=b[i]&(1<<bit);
if (a_bit && b_bit) /* logical AND */
o[i]=o[i]|(1<<bit);
}
}
}
int foo(void) {
unsigned int output_table[n];
both_tables(funky_table,aardvark_table,output_table);
return output_table[0];
}