Bit by bit

My first ever software programming language was C. Almost two decades later, in weird unexpected ways I find myself understanding software concepts, subconsciously in C.

Recently I had some really interesting conversation around how hashcode() in Java is critical for efficient storage and retrieval from HashMaps. One thing lead to another and the conversation veered onto bit operators, and its use in overriding hashcode(). Here, I was in for a bit of shock. I realized that my understanding of bitwise operators in Java was sketchy to say the least. I just recalled what I had done in my C days. I did not recall having actually tried out bitwise operators in Java ever. I am sure I would have, but I did not recall it.

Now this is something that had to be fixed. Immediately after the chat I went back to my machine and set out to play with the Java bitwise operators. Thankfully it was indeed the exact same as C (or at least the way I recollect them). I ended up writing some code to printout the bits (given an integer) and proceeded to play with integers and bitwise operators. Following is an example output of my code, for integer 256 where the code tries out different bitwise operators on it.

00000000000000000000000100000000[256]
& 00000000000000000000000000000010[2]
========================================
 00000000000000000000000000000000[0]

 00000000000000000000000100000000[256]
| 00000000000000000000000000000010[2]
========================================
 00000000000000000000000100000010[258]

 00000000000000000000000100000000[256]
^ 00000000000000000000000000000010[2]
========================================
 00000000000000000000000100000010[258]

~ 00000000000000000000000100000000[256]
========================================
 11111111111111111111111011111111[-257]

 00000000000000000000000100000000[256<<2]
========================================
 00000000000000000000010000000000[1024]

 00000000000000000000000100000000[256>>2]
========================================
 00000000000000000000000001000000[64]

 00000000000000000000000100000000[256>>>2]
========================================
 00000000000000000000000001000000[64]

Following is the same code for anyone else interested, to play with.
private static void printBinaryOperations(int operand1, int operand2){

System.out.printf("\t%s[%d]\n", toBinaryString(operand1), operand1) ;     
System.out.printf("&\t%s[%d]\n", toBinaryString(operand2),operand2) ;
System.out.printf("========================================\n") ;
System.out.printf("\t%s[%d]\n\n", toBinaryString(operand1 & operand2), (operand1 & operand2)) ;

System.out.printf("\t%s[%d]\n", toBinaryString(operand1), operand1) ;     
System.out.printf("|\t%s[%d]\n", toBinaryString(operand2),operand2) ;
System.out.printf("========================================\n") ;
System.out.printf("\t%s[%d]\n\n", toBinaryString(operand1 | operand2), (operand1 | operand2)) ;

System.out.printf("\t%s[%d]\n", toBinaryString(operand1), operand1) ;     
System.out.printf("^\t%s[%d]\n", toBinaryString(operand2),operand2) ;
System.out.printf("========================================\n") ;
System.out.printf("\t%s[%d]\n\n", toBinaryString(operand1 ^ operand2), (operand1 ^ operand2)) ;

System.out.printf("~\t%s[%d]\n", toBinaryString(operand1),operand1) ;
System.out.printf("========================================\n") ;
System.out.printf("\t%s[%d]\n\n", toBinaryString(~operand1), (~operand1)) ;

System.out.printf("\t%s[%d<<%d]\n", toBinaryString(operand1), operand1,operand2) ;
System.out.printf("========================================\n") ;
System.out.printf("\t%s[%d]\n\n", toBinaryString(operand1<<operand2), (operand1<<operand2)) ;

System.out.printf("\t%s[%d>>%d]\n", toBinaryString(operand1), operand1,operand2) ;
System.out.printf("========================================\n") ;
System.out.printf("\t%s[%d]\n\n", toBinaryString(operand1>>operand2), (operand1>>operand2)) ;

System.out.printf("\t%s[%d>>>%d]\n", toBinaryString(operand1), operand1,operand2) ;
System.out.printf("========================================\n") ;
System.out.printf("\t%s[%d]\n\n", toBinaryString(operand1>>>operand2), (operand1>>operand2)) ;

}

And here is the function that prints the bits of any given integer. There is a similar function in Integer class and I had started off with that, but I found that it chops off the leading 0s and that was not good enough for me.
private static String toBinaryString(int number) {
 char[] buf = new char[32];
 int charPos = 32;
 int mask = 1 ; 
 do {
  buf[--charPos] = ((number & mask)==0)? '0':'1'; 
     number >>>= 1;
 } while (charPos != 0);

 return new String(buf);
}

For further reading 
I found this article quite good. It gives a few neat usage of bitwise operators. Also I borrowed heavily from toUnsignedString(int i, int shift) in Integer class of Java.

If you want to get in touch, you can look me up at Linkedin or Google + .

No comments: