Complete Bit Manipulation and Bitwise Operation Tutorial in Java

Bitwise Operation includes some of the low level operations directly on bit representation. In this tutorial, I will cover the following bit operations and manipulations in Java:

  • AND
  • OR
  • XOR
  • COMPLEMENT
  • LEFT SHIFT
  • RIGHT SHIFT
  • UNSIGNED RIGHT SHIFT
  • SET NTH BIT TO ZERO
  • SET NTH BIT TO ONE

I have used both positive and negative numbers to show you the difference. Here is a summary of how these operations are done:

  • AND is represented by &. (For example¬†a & b)
  • OR¬† is represented by |. (For example a | b)
  • XOR is represented by ^ (For example a ^ b). If two bits are equal, result is 0 otherwise 1.
  • COMPLETEMENT is represented by ~ (flips the bits)
  • LEFT SHIFT is represented by <<
  • RIGHT SHIFT is represented by >> (preserves sign)
  • URSHIFT is represented by >>> (unsigned right shift – does not preserve sign)
  • Setting nth bit to 1: a = a | (1<<n)
  • Setting nth bit to 0: a = a & ~ (1<<n)

Here is the Java Implementation that shows all of the above operations:

package com.icodejava.blog.datastructure;

/**
 * @author Kushal Paudyal
 * www.icodejava.com
 * Created On -  Mar 1, 2014
 * Last Modified On - Mar 1, 2014
 */
public class BitManipulation {

	/**
	 * SUMMARY:
	 * 
	 * AND is represented by &
	 * OR  is represented by |
	 * XOR is represented by ^
	 * COMPLETEMENT is represented by ~ (flips the bits)
	 * LEFT SHIFT is represented by <<
	 * RIGHT SHIFT is represented by >> (preserves sign)
	 * URSHIFT is represented by >>> (unsigned right shift - does not preserve sign)
	 * Setting nth bit to 1: a = a | (1<<n)
	 * Setting nth bit to 0: a = a & ~ (1<<n)
	 */
	
	public static void main(String args[]) {
		int a = 5;
		int b = 6;

		doBitAND(a, b);
		doBitAND(-a, b);

		doBitOR(a, b);
		doBitOR(-a, b);

		doBitXOR(a, b);
		doBitXOR(-a, b);

		doBitComplement(a);
		doBitComplement(-a);

		doBitLeftShift(a, 1); // shift one bit left
		doBitLeftShift(-a, 2); // shift two bits left on -ve number

		doBitRightShift(a, 1); // shift one bit right
		doBitRightShift(-a, 2); // shift two bits right on -ve number

		doBitUnsignedRightShift(a, 1); // shift one bit right, sign not
										// preserved
		doBitUnsignedRightShift(-a, 2); // shift two bits right on -ve number,
										// sign not preserved

		setNthBitToZero(a, 2);
		setNthBitToZero(-a, 1);

		setNthBitToOne(a, 1);
		setNthBitToOne(-a, 2);

	}

	/**
	 * AND is represented by & such as num1 & num2
	 */
	public static int doBitAND(int a, int b) {
		System.out.println("{BITWISE AND OPERATION}\nFirst Number: " + a + "("
				+ Integer.toBinaryString(a) + ") Second Number: " + b + "("
				+ Integer.toBinaryString(b) + ")");

		int result = a & b;

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;

	}

	/**
	 * OR is represented by | such as num1 | num2
	 */
	public static int doBitOR(int a, int b) {
		System.out.println("{BITWISE OR OPERATION}\nFirst Number: " + a + "("
				+ Integer.toBinaryString(a) + ") Second Number: " + b + "("
				+ Integer.toBinaryString(b) + ")");

		int result = a | b;

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;

	}

	/**
	 * OR is represented by | such as num1 ^ num2
	 */
	public static int doBitXOR(int a, int b) {

		System.out.println("{BITWISE XOR OPERATION}\nFirst Number: " + a + "("
				+ Integer.toBinaryString(a) + ") Second Number: " + b + "("
				+ Integer.toBinaryString(b) + ")");

		int result = a ^ b;

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;

	}

	/**
	 * COMPLEMENT is represented by ~ such as ~num
	 */
	public static int doBitComplement(int a) {

		System.out.println("{BITWISE COMPLEMENT OPERATION}\nInput Number: " + a
				+ "(" + Integer.toBinaryString(a) + ")");

		int result = ~a;

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;
	}

	/**
	 * Left shift operation is represented with <<
	 * This operation preserves sign.
	 * Note: one bit left shift is equivalent to number multiplied by two.
	 */
	public static int doBitLeftShift(int a, int numberOfShifts) {

		System.out.println("{BITWISE LEFT SHIFT OPERATION}\nInput Number: " + a
				+ "(" + Integer.toBinaryString(a) + ") Number of bit shifts: "
				+ numberOfShifts);

		int result = a << numberOfShifts;

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;

	}

	/**
	 * Right shift operation is represented with >>
	 * This operation preserves sign.
	 */
	public static int doBitRightShift(int a, int numberOfShifts) {

		System.out.println("{BITWISE RIGHT SHIFT OPERATION}\nInput Number: "
				+ a + "(" + Integer.toBinaryString(a)
				+ ") Number of bit shifts: " + numberOfShifts);

		int result = a >> numberOfShifts;

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;

	}

	/**
	 * Unsigned Right shift operation is represented with >>>
	 * This operation does not preserve sign.
	 */
	public static int doBitUnsignedRightShift(int a, int numberOfShifts) {
		System.out
				.println("{BITWISE UNSIGNED RIGHT SHIFT OPERATION}\nInput Number: "
						+ a
						+ "("
						+ Integer.toBinaryString(a)
						+ ") Number of bit shifts: " + numberOfShifts);

		int result = a >>> numberOfShifts;

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;
	}

	/**
	 * To set nth bit to zero, we follow the following: a = a | (1 << n);
	 * Note: bit count starts with index zero from right.
	 */
	public static int setNthBitToOne(int a, int whichBit) {
		System.out
				.println("{BITWISE SET NTH BIT TO ONE OPERATION}\nInput Number: "
						+ a
						+ "("
						+ Integer.toBinaryString(a)
						+ ") Bit to set one: " + whichBit);

		int result = a = a | (1 << whichBit);

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;
	}

	/**
	 * To set nth bit to one, we follow the following: a & ~(1 << n);
	 * Note: bit count starts with index zero from right.
	 */
	public static int setNthBitToZero(int a, int whichBit) {
		System.out
				.println("{BITWISE SET NTH BIT TO ZERO OPERATION}\nInput Number: "
						+ a
						+ "("
						+ Integer.toBinaryString(a)
						+ ") Bit to set zero: " + whichBit);

		int result = a & ~(1 << whichBit);

		System.out.println("Result: " + result + "("
				+ Integer.toBinaryString(result) + ")\n");

		return result;
	}

}


Result of running the above program:

{BITWISE AND OPERATION}
First Number: 5(101) Second Number: 6(110)
Result: 4(100)

{BITWISE AND OPERATION}
First Number: -5(11111111111111111111111111111011) Second Number: 6(110)
Result: 2(10)

{BITWISE OR OPERATION}
First Number: 5(101) Second Number: 6(110)
Result: 7(111)

{BITWISE OR OPERATION}
First Number: -5(11111111111111111111111111111011) Second Number: 6(110)
Result: -1(11111111111111111111111111111111)

{BITWISE XOR OPERATION}
First Number: 5(101) Second Number: 6(110)
Result: 3(11)

{BITWISE XOR OPERATION}
First Number: -5(11111111111111111111111111111011) Second Number: 6(110)
Result: -3(11111111111111111111111111111101)

{BITWISE COMPLEMENT OPERATION}
Input Number: 5(101)
Result: -6(11111111111111111111111111111010)

{BITWISE COMPLEMENT OPERATION}
Input Number: -5(11111111111111111111111111111011)
Result: 4(100)

{BITWISE LEFT SHIFT OPERATION}
Input Number: 5(101) Number of bit shifts: 1
Result: 10(1010)

{BITWISE LEFT SHIFT OPERATION}
Input Number: -5(11111111111111111111111111111011) Number of bit shifts: 2
Result: -20(11111111111111111111111111101100)

{BITWISE RIGHT SHIFT OPERATION}
Input Number: 5(101) Number of bit shifts: 1
Result: 2(10)

{BITWISE RIGHT SHIFT OPERATION}
Input Number: -5(11111111111111111111111111111011) Number of bit shifts: 2
Result: -2(11111111111111111111111111111110)

{BITWISE UNSIGNED RIGHT SHIFT OPERATION}
Input Number: 5(101) Number of bit shifts: 1
Result: 2(10)

{BITWISE UNSIGNED RIGHT SHIFT OPERATION}
Input Number: -5(11111111111111111111111111111011) Number of bit shifts: 2
Result: 1073741822(111111111111111111111111111110)

{BITWISE SET NTH BIT TO ZERO OPERATION}
Input Number: 5(101) Bit to set zero: 2
Result: 1(1)

{BITWISE SET NTH BIT TO ZERO OPERATION}
Input Number: -5(11111111111111111111111111111011) Bit to set zero: 1
Result: -7(11111111111111111111111111111001)

{BITWISE SET NTH BIT TO ONE OPERATION}
Input Number: 5(101) Bit to set one: 1
Result: 7(111)

{BITWISE SET NTH BIT TO ONE OPERATION}
Input Number: -5(11111111111111111111111111111011) Bit to set one: 2
Result: -1(11111111111111111111111111111111)