
/*
 Bitwise and: &
int x = 0xABCD;   // …0000 1010 1011 1100 1101
int y = 0xFF;     // …0000 0000 0000 1111 1111
int z = x & y;    // …0000 0000 0000 1100 1101 == 0xCD

Bitwise or: |
int x = 0x60;    // …0110 0000
int y = 0x3B;    // …0011 1011
int z = x | y;   // …0111 1011 == 0x7B 

Left shift: <<
int z = 0xF << 4; //shift 0xF 4 bits to the left. 0xF0

Arithmetic Right shift: >>. (fill with sign bit)
int z = 0xAB >> 4;        //shift 0xAB 4 bits right. 0xA.
int z2 = 0x81234567 >> 4; //shift a negative number right.
						  //0xF8123456
																
Logical Right shift: >>> (fill with 0)
int z2 = 0x81234567 >> 4; //shift a negative number right.
                          //0x08123456

 */

public class BinaryIntegers {

	static int s_count = 0;
	
	public static void printValue(String label, int value) {
		//print label in 20 spaces
		System.out.printf("%d: %s\n", ++s_count, label);
		
		//print the decimal representation of value
		System.out.printf("\tDEC: %d\n", value);
		
		//print the Hexadecimal representation of value
		//Note %08X: pad up to 8 hex digits with 0s
		//  need to print the 0x
		System.out.printf("\tHEX: 0x%08X\n", value);
		
		//print the binary representation of value
		//first create it as a string
		System.out.printf("\tBIN: %s\n\n", Integer.toBinaryString(value));
	}
	
	public static void main(String[] args) {
		//a hex value
		int hex = 0xDEADBEEF;
		
		printValue("32 bit int", hex);

		//least significant 2 bytes (4 hex digits)
		//0xFFFF is 16 0's followed by 16 1's
		//&  is the bitwise and, so the result is each binary digit of hex
		//anded with each binary digit of 0xFFFF
		printValue("2 least sig. bytes", hex & 0xFFFF);
		
		//most significant 4 bytes
		//shift the value to the right, sign extended (fill in with the most significant bit)
		//this preserves negative numbers
		printValue("arith. shift right", hex >> 16);
		
		//try logical shift - no sign extensions (fill in with 0's)
		printValue("logical shift right", hex >>> 16);
		
		//The following are the same:
		// 256
		// 2 to the 8th 
		// 1 << 8 
		// 1 0000 0000  in binary
		
		//a note about div and mod, applying them to a negative value will produce
		//  a negative result
		//using div  
		printValue("AB76 div 256", 0xAB76 / 256);
		
		//using mod
		printValue("AB76 mod 256", 0xAB76 % 256);
		
		//See constants below the main
		
		//we can combine flags with bitwise or (or addition) to remember them in one value.
		int flags = IS_VALID | IS_WRITABLE;
		printValue("Flags variable", flags);
		
		//we can then check to see if a particular flag is set using bitwise and
		if((flags & IS_WRITABLE) != 0) {
			//here is the math:
			//writable  0100
			//flags     0101
			//        & 0100
		}
		
	}
	
	//using bits for multiple booleans
	//each flag is represented by a single bit in a different position
	//this allows us to combine them without changing their values
	static int IS_VALID = 1;   //1 0x1
	static int IS_READABLE = 1 << 1;   //2  0x2
	static int IS_WRITABLE = 1 << 2;  //4  0x4
	static int IS_SOMETHING_ELSE = 1 << 3;  //8  0x8
	
}
