Created: 2023-08-23 15:25
Status: #concept
Subject: Programming
Tags: Java Byte Boolean Algebra

Bitwise Operator

They are Operators that act directly on the internal Byte representation of the operands.

  • they act just like Boolean Algebra operators like OR, AND, XOR, COMPLEMENT (negation), etc.

List of Operators

  • ~ or COMPLEMENT, is equivalent to A', so 0' = 1.
  • | or OR, is equivalent to A + B, so 0 + 1 = 1.
  • & or AND, is equivalent to A * B, so 0 * 1 = 0.
  • ^ or XOR, is equivalent to (A*B)' ^ (A+B), so 0 xor 1 = 1, but 1 xor 1 = 0.

a = 5 = 0101 (In Binary)
b = 7 = 0111 (In Binary)

Bitwise OR Operation of 5 and 7
  0101
| 0111
 ________
  0111  = 7 (In decimal)
a = 5 = 0101 (In Binary)
b = 7 = 0111 (In Binary)

Bitwise AND Operation of 5 and 7
  0101
& 0111
 ________
  0101  = 5 (In decimal)
a = 5 = 0101 (In Binary)
b = 7 = 0111 (In Binary)

Bitwise XOR Operation of 5 and 7
  0101
^ 0111
 ________
  0010  = 2 (In decimal)
a = 5 = 0101 (In Binary)

Bitwise Complement Operation of 5

~ 0101
 ________
  1010  = 10 (In decimal)

Bitshift (Shift) Operators

They are used to shift the bits to the left (thus multiplying by a power of 2), or to the right (dividing by a power of 2).

List of Operators

  • << Signed Left Shift x << n does x * Math.pow(2, n).
  • <<< Unsigned Left Shift x <<< n does the same as above, but ignores the sign bit, therefore retaining the number's sign.
  • >> Signed Right Shift x >> n does x / Math.pow(2, n).
  • >>> Unisigned Right Shift acts similar to <<<.

public class Test {
    public static void main(String[] args) {
        int i = 1;
        i = i << 2;
        
        System.out.println("Original value of i: " + i);
        System.out.println("New value of i: " + i);
    }
}
// Original value of i: 4
// New value of i: 4

Visual Representation

6
00000000 00000000 00000000 00000110
 
12
00000000 00000000 00000000 00001100

Non-circular Shifting

When we shift bits outside its boundaries, it will truncate the bits out.

3,758,096,384
11100000 00000000 00000000 00000000

3,221,225,472
11000000 00000000 00000000 00000000
#include <stdio.h>

void printBitPattern(int n) {
    int dataSize = sizeof(n) * 8; // data type size in bytes * number of bits in a byte = bits length
    int shiftOffset;
    int count = 1; // for pretty printing

    // we offset every bit to the right to do an AND (&) operation to print the bit at that offset
    for (shiftOffset = dataSize - 1; shiftOffset >= 0; shiftOffset--) {
      printf("%d", (n >> shiftOffset) & 1);
      (count++ % 4 == 0) ? printf(" ") : printf(""); // pretty print spaces every 4 bits
    }
}

int main(void) {
  printBitPattern(4);
}

Use Cases

Odd or Even

We can simply & the first bit of a value, which represents the Math.pow(2, 0) or 1 value place, to check if 1 is added to the number.

  • since all other bits represent a Math.pow(2, n) value (which are all divisible by 2), they are all considered as 2k.
  • since odd numbers are defined as 2k + 1, the 1 bit denotes whether it satisfies this definition.

public class Test {
    public static void main(String[] args) {
        int num1 = 123;
        int num2 = 9990;
        int num3 = 9017235;
        
        System.out.println(isOdd(num1)); // true
        System.out.println(isOdd(num2)); // false
        System.out.println(isOdd(num3)); // true
    }
    
    private static boolean isOdd(int num) {
        return ((num & 1) == 0) ? false : true;
    }
}

References