| Felix Halim .NET | ||
|
University Experience
IOI 2002 Yong In, Korea
ACM ICPC Regional Manila 2003
ACM ICPC Regional Manila 2004
ACM ICPC Regional Manila 2005
ACM ICPC Regional Kaohsiung 2006
ACM ICPC Regional Singapore 2007
ACM ICPC World Final Tokyo 2007
Google India Code Jam 2005
Google India Code Jam 2006
Indonesia National Contest 2007
Indonesia National Contest 2008
|
||
Bitwise OperationBitwise means working at the level of single bits (rather than larger data units) -> copied from "Babylon Translator". In C, bitwise operators are & (AND), | (OR), ^ (XOR), ~ (NOT), << (SHIFT LEFT), >> (SHIFT RIGHT) To be able to understand bitwise operation, you have to be very familiar with base 2. That is, numbers consist of zeros and ones. All of these operators operate in base 2. If you are using 32 bit C compiler, then an int variable is 32 bit length. Why is 16 bits compiler and 32 bits compiler are put into our consideration? Because they will behave differently on some cases! see the examples below, you will understand it automatically. During bitwise operation, you have to align right the bits! (just like addition, multiplication,...) & (AND) operator
This table will clearly explains the bitwise operator & (AND): Example: 24052 -> 101110111110100 4978 -> 1001101110010 Now, AND the numbers : (shorter bits can have trailing zeros at the front)
24052 -> 101110111110100
4978 -> 001001101110010
----------------- &
001000101110000 -> 4464
Each bit-column is AND-ed using the AND table above. The result of 24052 & 4978 = 4464. | (OR) operatorThis table summarize the OR operations : Now, using the same example above, let's do it using | (OR) operator :
24052 -> 101110111110100
4978 -> 001001101110010
----------------- |
101111111110110 -> 24566
Each bit-column is OR-ed using the OR table above.^ (XOR) operatorThis table summarize the OR operations : Now, using the same example above, let's do using | (OR) operator :
24052 -> 101110111110100
4978 -> 001001101110010
----------------- |
100111010000110 -> 20102
Easy, isn't it?Now, the hard parts : ~ (NOT) operatorThis operator is different from the above operators. This operator is called unary operator, since it only needs one operand. Operand is the number to be operated. The operators &, |, ^ are binary operators, since it takes 2 operands/number to be operated. This ~ (NOT) operator, inverts all the bits in a variable. That is, changes all zeros into ones, and changes all ones into zeros. Remember! that the result of this ~ (NOT) operation, is highly depends on the length of the bit in a variable! Example: int a = 10;The output is -11. To understand how in the hell -11 come from, you have to understand about binary representation of negative integers of an int variable! Look at the operation of 16 bit C compiler : (that is, an int variable is 16 bits long)
a = 10 -> 0000000000001010 (16 bits)
------------------ ~
1111111111110101 -> -11
This is correct! Because computer stores -11 as 1111111111110101 in binary! (If you don't believe, you can read a computer organization book, or digital design book, or else that talks about how computer stores negative numbers).
Anyway, if you don't have time to read the book, just change the printf argument to show the unsigned value of ~a : int a = 10;The output is 65525. Now, it makes sense!
Argument %u will print the unsinged value of ~a. Don't be surprised if you got the output of the unsigned value of -11 is 4294967285.
a = 10 -> 00000000000000000000000000001010 (32 bits)
--------------------------------- ~
11111111111111111111111111110101 -> -11 (for signed)
-> 4294967285 (for unsigned)
Is that clear?
<< (SHIFT LEFT) operatorThis operator is mostly used if someone would like to multiply a number by 2 or power of 2. This operator is also depends highly on the length of the bits of an int variable. Actually this operator only "shift" or moves all the bits to the left. Example : (I use 16 bit C compiler -> IMPORTANT)
int a = 4978;
printf("%d",a<<1);
The output will be 9956.
Do you see the relation of 4978 with 9956? For more detailed explanation, I will operate it in base 2 :
a = 4978 -> 0001001101110010 (16 bit)
------------------ << 1 (SHIFT LEFT the bits by one bit)
0010011011100100 -> 9956
Just move left all the bits by one. The left most bit is lost! and at the rightmost, a zero is added.
Second example: count 4978 << 8 (count 4978 shifted left by 8 bits)
4978 -> 0001001101110010 (16 bit)
------------------ << 8 (SHIFT LEFT the bits by 8 bit)
0111001000000000 -> 29184
So, using 16 bit compiler, 4978 << 8 is 29184.You can see that some of the left bits are lost... It will not, however, if you use 32 bit compiler! AGAIN! Don't be surprised if you got the output of 4978 << 8 is 1274368.
4978 -> 00000000000000000001001101110010 (32 bit)
---------------------------------- << 8 (SHIFT LEFT the bits by 8 bit)
00000000000100110111001000000000 -> 1274368
As you can see, no bits are lost after shifting the bits left by 8 bits if you use 32 bit compiler!That's why 16 bit compiler and 32 bits compiler are put into our consideration... Note that you don't have to have an int to store the value! In C, you can just print like this :
printf("%d", 4978 << 8);
The output will be 29184 for 16 bit compiler as Turbo C (Some bits will be lost)The output will be 1274368 for 32 bit compiler as GNU C (All bits are reserved since it has bigger capacity) Now you know why shifting left 1 bit is the same as multiply the number by 2 right? If you notice: 4978 << 8 = 1274368 (in 32 bits compiler) 4978 * 28 = 4978 * 256 = 1274368. (exactly the same, isn't it)I use 32 bit, because in 16 bit compiler, the left bits are lost! (hence will produce wrong answer) BTW, you know why 4978 << 8 is the same as 4978 * 28, don't you? >> (SHIFT RIGHT) operatorNot much different with << (SHIFT LEFT) operator. It just shift all the bits to the right instead to the left. This operator is mostly used if you want to divide a number by 2, or other division by the power of 2.
Example : count 4978 >> 8 Answer : 4978 >> 8 = 19 (in 16 bits compiler or 32 bits compiler, they both produce the same output) I'm sure you do know why 16 or 32 bits compiler will result the same result for >> (SHIFT RIGHT) operator. Detailed explanation :
4978 -> 0001001101110010 (16 bit)
------------------ >> 8 (SHIFT RIGHT the bits by 8 bit)
0000000000010011 -> 19
4978 -> 00000000000000000001001101110010 (32 bit)
---------------------------------- >> 8 (SHIFT RIGHT the bits by 8 bit)
00000000000000000000000000010011 -> 19
If you notice: 4978 >> 8 = 19 (in 32 bits compiler) 4978 / 28 = 4978 / 256 = 19. (They both the same, but using bitwise operator >> (SHIFT RIGHT) is a LOT faster!) SuggestionsDo use bitwise operations instead of other mathematical operators such as * (MULTIPLICATION), / (DIVISION), + (ADDITION), - (SUBTRACTION). Because bitwise operators are A LOT FASTER than those operators. But, give comment as the replacement for the readibility of your own source code! Since not so many people understand bitwise operations! They are too afraid to use them somehow, I don't know why... Just drag those people to this page, they will thank you :) Please contact me if I'm wrong, click here |
||