## Bitwise operations

Overview

Bitwise operations act upon individual bits within integer data. They are used to perform the logical operations AND, OR, and XOR (eXclusive OR), complementing (reversing all bits), and shifting (sliding bits to the left or right).

Logical bitwise operations

• Use the standard boolean operators (&, |, and ^) to act upon two integer values. The short-circuit boolean operators (&& and ||) are not used for bitwise operations and will result in a compile error if attempted.

• Produce an integer result (of size int or larger) that is the logical AND, OR, or XOR of two operands. The rules for these operations are as follows:

 Operation Rule & If both corresponding operand bits are "on" the result bit is "on" | If either corresponding operand bit is "on" the result bit is "on" ^ If corresponding operand bits are different the result bit is "on"

For example, if

byte x = 5;    // Binary value:  0000 0101  Hex value: 05
byte y = 9;    // Binary value:  0000 1001  Hex value: 09
byte z;

this table shows the result of executing three unrelated statements. The cast is needed in order to store the int value that results from the operation.

 Statement Binary Result Hexadecimal Decimal z = (byte)(x & y); 0000 0001 01 01 z = (byte)(x | y); 0000 1101 0D 13 z = (byte)(x ^ y); 0000 1100 0C 12

Example: The following program can be run to test logical bitwise operations.

public class App {
public static void main(String[] args) {

// Variables to be read from the user

int first;
int second;

// Prompt for and read the two integers

System.out.print("First integer: ");
System.out.print("Second integer: ");

// Display the results of logical bitwise operations

System.out.println("\n\t" + first + " & " + second + " = " +
(first & second));
System.out.println("\t" + first + " | " + second + " = " +
(first | second));
System.out.println("\t" + first + " ^ " + second + " = " +
(first ^ second));
}
}

Notes:

1. Program results are displayed in decimal. To really understand what is happening, work out the equivalent binary and hexadecimal values.

2. Be sure to run the program several times with different integer values.

The complement operator

• Is unary (has a single operand)

• Uses the ~ operator to "flip" (reverse) the bits within an integer value. If a bit is "on" it is turned "off". If a bit is "off" it is turned "on".

For example, if

byte a = 17;   // Binary value:  0001 0001  Hex value: 11
byte b;

after executing the statement

b = (byte) ~a;

variable b will have a value of -18 (because 0001 0001 reverses to 1110 1110). Once again, the cast is needed in order to store the int value that results from the operation.

Example: The following program can be run to test complement operations.

public class App {
public static void main(String[] args) {

// Variable to be read from the user

int number;

// Prompt for and read an integer value

System.out.print("Integer: ");

// Display the result of complementing the number

System.out.println("\n\t~" + number + " = " + ~number);
}
}

Notes:

1. Again, program results are displayed in decimal so work them out in binary to understand what is happening.

2. The sign of a number changes when it is complemented due to the sign bit being reversed.

3. Be sure to run the program several times with different integer values.

Bitwise shift operations

• Shift the bits of the first integer operand the number of bits specified by the second integer operand. The operator used determines the direction of the shift and whether the sign of the number is to be maintained.

• The maximum number of bit positions that can be shifted is 31 bits. If the second operand specifies a shift value greater than 31, only its right-most 5 bits will be used as the shift value. In other words, a shift factor of 32 is the same as a shift factor of 0.

• Use the << (left shift), >> (signed right shift), and >>> (unsigned right shift) operators. The rules for these operations are as follows:

 Operation Rule << Shifts the first operand to the left the number of bits specified by the right-most 5 bits of the second operand. The low-order bit of the first operand is replaced with binary 0. >> Shifts the first operand to the right the number of bits specified by the right-most 5 bits of the second operand. The sign bit of the first operand is shifted and replaced with its original value (so the sign is maintained). >>> Shifts the first operand to the right the number of bits specified by the right-most 5 bits of the second operand. The sign bit of the first operand is shifted and replaced with binary 0.

For example, if

byte x = 7;    // Binary value:  0000 0111  Hex value: 07
byte y;

this table shows the result of executing three unrelated statements. The cast is needed in order to store the int value that results from the operation.

 Statement Binary Result Hexadecimal Decimal y = (byte)(x >> 2); 0000 0001 01 01 y = (byte)(x << 2); 0001 1100 1C 28 y = (byte)(x >>> 3); 0000 0000 00 00

Example: The following program can be run to test bitwise shift operations.

public class App {
public static void main(String[] args) {

// Variables to be read from the user

int first;
int second;

// Prompt for and read the two integers

System.out.print("First integer: ");
System.out.print("Second integer: ");

// Display the results of bitwise shift operations

System.out.println("\n\t" + first + " << " + second + " = " +
(first << second));
System.out.println("\t" + first + " >> " + second + " = " +
(first >> second));
System.out.println("\t" + first + " >>> " + second + " = " +
(first >>> second));
}
}

Notes:

1. Program results are displayed in decimal. To really understand what is happening, work out the equivalent binary and hexadecimal values.

2. Be sure to run the program several times with different integer values.

Bitwise assignment operations

• All bitwise operators except the unary complement (~) can be combined with assignment as long as the first operand is an integer variable. For example,

int x = 23;
x <<= 2;
System.out.println("Now x is " + x);

will display "Now x is 92" because 0000 0017 shifted 2 bits to the left becomes 0000 005C.

• Do not require casts to prevent compile errors. Possible data loss is ignored (so be careful). For example,

byte x = 127;
x |= 256;
System.out.println("Now x is " + x);

will display "Now x is 127" because 7F OR 0000 0100 results in 0000 017F (decimal 383) but only the right-most 8 bits are assigned to byte variable x.

More practice

The Java ranch tutorial Cat and Mouse Games with Bits ends with an applet you can use to practice bitwise operations.

Review questions

1. If x is short variable with a decimal value of 27, what data type and decimal value will result from executing the following expression?

x & 8

1. a short with a value of 8

2. an int with a value of 8

3. a short with a value of 27

4. an int with a value of 27

5. a short with a value of 19

1. If someNumber is an int variable having some value, what value will it have after executing the following statement?

1. the statement will not compile

2. the statement will compile but an error will occur at run time

3. 0

4. -1

5. the value cannot be determined from the information given

1. If amount is a short variable with a decimal value of 6, which of the following statements will multiply amount by four and store the result in a short variable named newAmount?  (choose two)

1. newAmount = (short) (amount << 2);

2. newAmount = amount << 2;

3. newAmount = (short) (amount >> 2);

4. newAmount = amount >> 2;

5. newAmount = (short) (amount << 34);

1. If x is an int variable with an initial value of 7, what value will it have after executing the following?

x >>>= (x ^ 6);

1. 0

2. 3

3. 14

4. 448

5. the statement will not compile