Interesting bit operations in JAVA

Interesting bit operations in JAVA

&, |, ^, ~ What do these symbols mean? What's the magical effect? Let's feel their magic together~

When we look at some source code, we often see symbols such as &, |, ^, ~, these are bitwise operators.

Bit arithmetic is to directly operate on a reshaped binary bit. The efficiency is much higher than that of addition, subtraction, multiplication and division, so it is often used in performance-sensitive scenarios.

& And operation

In the binary format, each bit (1 or 0) of the two numbers is AND (1&1=1, others=0) to get a new binary number.

public class Bit {
    public static void main(String[] args) {
       /*
         * Decimal binary
         * 5 0 1 0 1 The comparison starts from the lowest bit (right), and the less than 0
         * And and
         * 14 1 1 1 0
         * = =
         * 4 0 1 0 0
         */
        System.out.println(5 & 14);
    }
}
//output: 4

Determine whether the integer n is odd or even:

  • n & 1 = 0 even
  • n & 1 = 1 odd

Principle: In binary format, if the first digit on the right is 0, it is an even number, and vice versa, it is an odd number, so it only needs to be ANDed with 1.

| Or operation

In the binary format, each bit (1 or 0) of the two numbers is ORed (0|0=0, others=1) to get a new binary number.

public class Bit {
    public static void main(String[] args) {
       /*
         * Decimal binary
         * 2 0 1 0 The comparison starts from the lowest bit (right), the insufficient is 0
         * Or or
         * 4 1 0 0
         * = =
         * 6 1 1 0
         */
        System.out.println(2 | 4);
    }
}
//output: 6

In the Linux system, file authority management uses 1, 2, and 4 to indicate the authority to execute x, write w, and read r, respectively.

It can be regarded as a three-digit binary number, each of which indicates whether a permission is on or off (1 is on, 0 is off), and different permission combinations are obtained through the combination of OR operations.

So the highest authority is 7, which is the binary "111", which has all read, write, and execute permissions. The 777 authority means that the user, group user, and other users all have the highest authority.

Based on this idea, we only need an int or long number to store dozens of boolean attribute values, which is useful in certain scenarios.

^ XOR operation

XOR: Same as false, different from true

In the binary format, each bit (1 or 0) of the two numbers is XORed (0^0=0, 1^1=0, others=1) to obtain a new binary number.

public class Bit {

    public static void main(String[] args) {
       /*
         * Decimal binary
         * 2 0 1 0 The comparison starts from the lowest bit (right), the insufficient is 0
         * XOR
         * 6 1 1 0
         * = =
         * 4 1 0 0
         */
        System.out.println(2 ^ 6);
    }
}
//output: 4

XOR has an interesting feature, its inverse operation is itself, namely A^B=C, C^B=A. Based on this feature, a simple encryption can be made, using B as the secret key, the original text A is encrypted with secret key B for transmission or storage, etc., and then secret key B is used for decryption when in use.

The exchange of two numbers can also be achieved through the exclusive OR operation, without intermediate values. (I simply tested the performance and it was not great)

public class Bit {

    public static void main(String[] args) {
        int x = 2;//010
        int y = 4;//100
        x = x ^ y;//110
        y = y ^ x;//010
        x = x ^ y;//100
        System.out.println("x = "+ x);
        System.out.println("y = "+ y);
    }
}

/* Output:

x = 4
y = 2

*/

~ Not arithmetic

In the binary format, each digit (1 or 0) of the two numbers is negated (~0=1, ~1=0) to obtain a new binary number.

public class Bit {

    public static void main(String[] args) {
        System.out.println(~1);
    }

}
//output: -2

After 1 is negated, the value becomes negative, not just 1, as long as it is positive, it is negative after negation, because for signed integers, the highest bit (leftmost) is used to indicate positive and negative, and the highest bit is 0 Is a positive number, 1 is a negative number.

After the positive number 1 is negated, "00000000000000000000000000000001" becomes "11111111111111111111111111111110".

When binary represents a negative number, it takes two steps to convert to decimal:

  1. Inverted bit by bit -> 00000000000000000000000000000001 (binary)
  2. Add 1 -> 00000000000000000000000000000010 (binary) -> 2 (decimal)
  3. Plus minus sign -> -2 (decimal)

summary

Some purposes can be achieved ingeniously and efficiently through bit operations, but if it is not necessary, it is not recommended. After all, the readability is not high, and others seem too painful (think about seeing a bunch of bit operations when reading the source code Mood).

This time I briefly introduced AND, OR, NOT, XOR, and I'll talk about the practice of shift operations next time.