User Professor Hans Noodles
Professor Hans Noodles
Level 41

Bitwise operators

Published in the Java Developer group
You're probably familiar with the word "bit". If not, let's recall what it means :) A bit is the smallest unit of information in a computer. Its name comes from binary digit. A bit can be expressed by one of two numbers: 1 or 0. There is a special binary number system based on ones and zeros.
Bitwise operators - 1
We won't delve into a mathematical jungle here. We'll only note that any number in Java can be converted into binary form. To do this, you need to use the wrapper classes. For example, here's how you can do this for an int:

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Console output: 101010110 1010 10110 (I added the space to make it easier to read) is the number 342 in the decimal system. We've actually broken this number down into individual bits: zeros and ones. Operations performed on bits are called bitwise.
  • ~ - bitwise NOT.
This operator is very simple: it passes over each bit of our number, and flips the bit: zeros become ones, and ones become zeros. If we apply it to our number 342, here's what happens: 101010110 is 342 represented as a binary number 010101001 is the value of the expression ~342 Let's try to put this into practice:

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(~x);
   }
}
Console output: 169 169 is our result (010101001) in the familiar, decimal system :)
  • & - bitwise AND
As you can see, it looks quite similar to the logical AND (&&). The && operator, you will recall, returns true only if both operands are true. Bitwise & works in a similar way: it compares two numbers bit by bit. The comparison produces a third number. For example, let's take the numbers 277 and 432: 110110000 is 277 represented as a binary number 1000101011 is 432 represented as a binary number Next, the operator & compares the first bit of the upper number to the first bit of the bottom number. Because this is an AND operator, the result will be 1 only if both bits are 1. In any other case, the result is 0. 100010101 & 110110000 _______________ 10001000 - result of the & operator First, we compare the first bits of the two numbers, then the second bits, then the third, and so on. As you can see, in only two cases are both corresponding bits in the numbers equal to 1 (the first and fifth bits). All other comparisons produced 0s. So in the end we got the number 10001000. In the decimal system, it corresponds to the number 272. Let's check:

public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Console output: 272
  • | - bitwise OR.
This operator works in the same way: comparing two numbers bit by bit. Only now if at least one of the bits is 1, then the result is 1. Let's look at the same numbers (277 and 432): 100010101 | 110110000 _______________ 110110101 - result of the | operator Here's we get a different result: the only bits that remain zeros are those bits that were zeros in both numbers. The result is the number 110110101. In the decimal system, it corresponds to the number 437 Let's check:

public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Console output: 437 We calculated everything correctly! :)
  • ^ - bitwise XOR (exclusive OR)
We haven't yet encountered this operator. But there's nothing complicated about it. It is similar to the ordinary OR operator. There is one difference: the ordinary OR returns true if at least one operand is true. But it doesn't have to be one: if both operands are true, the result is true. But exclusive OR returns true only if exactly one of the operands is true. If both operands are true, the ordinary OR returns true ("at least one true"), but XOR returns false. That's why it's called exclusive OR. Knowing how the previous bitwise operators work, you can probably easily calculate 277 ^ 432. But let's dig into it together one more time :) 100010101 ^ 110110000 _______________ 010100101 - result of the ^ operator That's our result. Those bits that were the same in both numbers produce a 0 (meaning the "only one" test failed). But the bits that formed a 0-1 or 1-0 pair became ones. Our result is the number 010100101. In the decimal system, it corresponds to the number 165. Let's see if our calculations are correct:

public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Console output: 165 Super! Everything is just as we thought :) Now it's time to get acquainted with bit shifts operators. The name speaks for itself. We take some number, and move its bits left or right :) Let's see how it looks:

Shift left

A shift of bits to the left is indicated by << Here's an example:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
In this example, the number x = 64 is called the value. It's the bits of the value that we'll shift. We'll shift the bits to the left (you could have guessed this by the direction of the << operator) In the binary system, the number 64 = 1000000 The number y = 3 is called shift distance. The shift distance indicates how many bits to the right/left you want to shift the bits of the number x In our example, we'll shift them 3 bits to the left. To see the shift process more clearly, look at the picture. In this example, we use ints. Ints occupy 32 bits in the computer's memory. This is how our original number 64 looks:
Bitwise operators - 2
And now we take each of our bits and literally shift them to the left by 3 places:
Bitwise operators - 3
Take a look at what we got. As you can see, all our bits have shifted, and another 3 zeros have been added from the edge of the range. Three, because we shifted by 3. If we had shifted by 10, 10 zeros would have been added. Thus, the expression x << y means "shift the bits of the number x to the left by y places". The result of our expression is the number of 1000000000, which is 512 in the decimal system. Let's check:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Console output: 512 Spot on! Theoretically, the bits could be shifted endlessly, but because our number is an int, we have only 32 binary digits available. Of these, 7 are already occupied by 64 (1000000). Therefore, if we shifted 27 places to the left, our only one would move beyond the data type's range and be lost. Only zeros would remain!

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 26;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Console output: 0 As expected, the one moved beyond the 32 available bits and disappeared. We ended with a 32-bit number consisting of only zeros.
Bitwise operators - 4
Naturally, this corresponds to 0 in the decimal system. Here's a simple rule for remembering shifts to the left: For each shift to the left, the number is multiplied by 2. Let's try to calculate the following expression without pictures of bits 111111111 << 3 We need to multiply the number 111111111 by 2. As a result, we get 888888888. Let's write some code and check:

public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
Console output: 888888888

Shift right

This operation is denoted by >>. It does the same thing, but in the other direction! :) We won't reinvent the wheel. Let's try it with the same int 64.

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 2;// Shift distance

       int z = (x >> y);
       System.out.println(z);
   }
}
Bitwise operators - 5
Bitwise operators - 6
As a result of a shift to the right by 2, the two extreme zeroes in our number move out of range and are lost. We get 10000, which corresponds to the number 16 in the decimal system Console output: 16 Here's a simple rule for remembering shifts to the right: Each shift to the right divides by two, discarding any remainder. For example, 35 >> 2 means that we need to divide 35 by 2 twice, discarding the remainders 35/2 = 17 (discard remainder 1) 17/2 = 8 (discard remainder 1) In the end, 35 >> 2 should be equal to 8. Let's check:

public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
Console output: 8

Operator precedence in Java

While writing and reading code, you'll often find expressions that combine several operations. It's very important to understand the order they will be executed in (otherwise, you may be surprised by the result) Because Java has lots of operations, each of them has been assigned a place in a special table:

Operator Precedence

Operators Precedence
postfix expr++ expr--
unary ++expr --expr +expr ~ !
Multiplicative * / %
additive + -
shift << >> >>>
relational < > <= >= instanceof
equality == !=
bitwise AND &
bitwise exclusive OR ^
bitwise inclusive OR |
logical AND &&
logical OR ||
ternary ? :
assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=
All operations are performed from left to right, taking into account their precedence. For example, if we write

int x  = 6 - 4/2;
then the division operation (4/2) will be performed first. Although it comes second, it has higher precedence. Parentheses and brackets indicate maximum precedence. You probably remember that from school. For example, if you add them to the expression

int x  = (6 - 4)/2;
then the subtraction is performed first, since it is enclosed in parentheses. The precedence of the logical && operator is rather low (see the table), so it will usually be last. For example:

boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
This expression will be executed as follows:
  • 4/2 = 2

boolean x = 6 - 2 > 3 && 12*12 <= 119;
  • 12*12 = 144

boolean x = 6 - 2 > 3 && 144 <= 119;
  • 6-2 = 4

boolean x = 4 > 3 && 144 <= 119;
Next, the comparison operators are executed:
  • 4 > 3 = true

boolean x = true && 144 <= 119;
  • 144 <= 119 = false

boolean x = true && false;
And, finally, the AND operator (&&) will be executed last.

boolean x = true && false;
boolean x = false;
For example, the addition(+) operator has a higher precedence than the != (not equal) comparison operator; Therefore, in the expression

boolean x = 7 != 6+1;
the 6+1 operation will be performed first, then the 7 != 7 check (which evaluates to false), and finally the assignment of the result (false) to the variable x (assignment generally has the lowest precedence of all operators; see the table). Phew! It was a huge lesson, but you did it! If you didn't fully understand some of this or previous lessons, don't worry. We'll touch on these topics more than once in the future. Here are some useful relevant links: Excellent illustrated article about bitwise operations Numeric operators Logical operators A couple of CodeGym lessons about logical and numerical operations. We won't get to these any time soon, but there's no harm in you reading them now.
Comments (54)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Jeffrey Janaczek Level 9, Tampa, United States
11 June 2021
// YOU CAN SIMPLY COPY, PASTE AND RUN EVERYTHING IN THIS... // POST SO YOU CAN SEE IT FOR YOURSELF public class Solution { public static void main(String[] args) throws Exception { //Regarding the following 2 lines of code: int x = 342; System.out.println(~x); // This tutorial says that the output should be 169. // When I run this in IntelliJ the output is -343. //AFTER DOING SOME RESEARCH: --------------------------------------------- // the complement of 01010110 is 10101001 (changing the one's to zeros and // the zeros to ones. //------------------------------------------------------------------------- // 01010110 as an integer is 342 // 10101001 as an integer is 169 System.out.println(Integer.parseInt((Integer.toBinaryString(342)))); // output: 101010110 System.out.println(Integer.parseInt((Integer.toBinaryString(169)))); // output: 10101001 System.out.println(Integer.parseInt("101010110", 2)); // output: 342 System.out.println(Integer.parseInt("10101001", 2)); // output: 169 //the reason that the following output is -343 is because... //the bitwise complement for integers is -(N+1) System.out.println(~342); // output: -343 //Hope this helps. } }
Jaime Padilla Level 7, Tempe, United States
22 April 2021
Why does the table show multiplication before division but in the example the division is performed first?
Maryam Roudbari Level 41
4 April 2021
He doesn't say how do we convert binary number to integer manually. Can anybody help me with that?
Juanf Level 25, Vilnius, Lithuania
11 February 2021
It says: 110110000 is 277 represented as a binary number 1000101011 is 432 represented as a binary number But: 1000101011 is not 432, but 555 and 110110000 is not 277, but 432
Daniel Whyte Level 17
9 January 2021
Found this really interesting.
Karol Level 13, Poland
20 November 2020
There is a little mistake. Because 100010101 & 110110000 (277&432) gives us this number 1 0001 0000 (272) not 1000 1000 (136). One zero on the end is missing.
Vitalina Level 19, Poland
5 October 2020
hm....I don't understand now where I can use it..
Chandan Thapa Level 22, Dubai, United Arab Emirates
5 October 2020
Love it!
Mihai Bone Level 8, Bucharest, Romania
4 October 2020
Nice..... but I hope I don't use them :D
pgalanty Level 41, Sochaczew, Poland
28 August 2020
cool, thanks for explaining ;)