1. 비트 연산자?
앞에서 배운 비트와 바이트의 개념을 다시 떠올릴 때가 되었다!
지금까지 배운 연산이 변수나 상수에 대한 연산이라면 비트 연산자는 비트 값을 기반으로 하기 때문이다.
비트 연산자는 말 그대로 비트 단위로 연산이 이루어지는 연산자이다.
비트 단위의 연산을 하는 경우는 '암호화' 작업처럼 임의의 숫자를 만들거나, 어떤 변수의 특정 비트를 꺼내보는(마스킹; masking) 경우에 사용한다.
또한 메모리 용량이 부족하거나 계산이 복잡해서 속도가 느려질 때 비트 연산자를 사용하면 어떤 수의 2배수, 4배수를 만들어 속도를 빠르게 만들 수 있다.
2. 비트 논리 연산자
비트 단위로 & , | , ^ , ~ 연산이 이루어진다.
하나씩 살펴보자!
1) & 연산자
&(AND) 연산자는 두 개의 비트 값이 모두 1인 경우에만 연산의 결과 값이 1이 된다.만약 5 & 10 을 연산하면 결과 값은 0이 된다....?
라고만 쓰면 이해가 잘 안된다.왜냐하면 십진수로 표현했기 때문이다.이 연산은 비트 단위로 연산되기 때문에 2진수로 바꾸어야 한다.
5 = 00000101& 10 = 00001010
------------------------
결과 = 00000000 // 0으로 출력
여기서 두 개의 비트 값이 1인 경우에 1이 된다는 뜻은 위 아래로 대조되는 각 자리 수의 두 비트 값이 모두 1이어야 한다는 것이다(더하기를 하듯 말이다).
** 예시 [ 0 & 0 // 0, 0 & 1 // 0, 1 & 1 // 1 ]
2) | 연산자
|(OR) 연산자는 비트 값이 하나라도 1이면 연산 결과 값이 1이 된다.위의 식을 | 연산자로 다시 결과값을 출력해보자.
5 = 00000101
| 10 = 00001010
------------------------
결과 = 00001111 // 15로 출력
3) ^ 연산자
^(XOR) 연산자는 같은 값이면 0, 다른 값이면 1의 결과를 갖는다.
5 = 00000101
^ 10 = 00001010
------------------------
결과 = 00001111 // 15로 출력
4) ~ 연산자
~(반전) 연산자는 비트 값을 0을 1로, 1을 0으로 바꾸는 연산자이다. 그래서 반전 연산자라고도 부른다.
다음은 10진수 10을 반전해보는 예시이다.
int num = 10;
int result = ~num;
10 = 00001010 이기에
~num = 11110101 이다.
이 경우 부호 비트가 1이 되었기에 음수가 되었고, 이 값을 구하기 위해서는 다시 양수로 변환해야 어느 수의 음수인지 알 수 있다. 더해서 0이 되는 2진수는 00001011이다. 이를 10진수로 변환하면 11이 되기에 ~num의 값은 -11이 된다.
3. 비트 이동 연산자
비트 이동 연산자는 << , >> , >>> 이렇게 세 가지가 있다.
이를 시프트(shift) 연산자라고도 부른다.
이 연산자들의 기능을 살펴봐보자!
1) << 연산자
<< 시프트 연산자는 왼쪽으로 비트를 이동하는 연산자이다.
int num = 5;
num << 2;
위의 예시에서 5, 그러니까 0000101에서 두 비트만큼 왼쪽으로 이동을 시키는 거다.
그러면 왼쪽의 00은 사라지고 오른쪽에 00이 붙는다.
이렇게 왼쪽으로 n비트 이동한다는 것은 기존 값에 2의 n승 만큼 곱한다는 뜻이다.
num << 2 의 결과로 0010100이 도출되어 20이 된다.
(5 * 2의 2승) = 20으로 계산할 수도 있다.
2) >> 연산자
>> 시프트 연산자는 오른쪽으로 비트를 이동하는 연산자다.
오른쪽으로 n비트 이동한다는 것은 기존 값을 2의 n승으로 나눈다는 뜻이다.
이 경우에 왼쪽에 채워지는 비트 값은 기존 값의 부호 비트와 동일하다.
3) >>> 연산자
>>> 시프트 연산자는 >> 연산과 동일하게 비트를 오른쪽으로 이동한다.
차이가 있다면 >>> 연산자는 왼쪽에 채워지는 비트 값이 부호 비트와 상관없이 무조건 0이 된다.
아래의 예재를 통해 확인해보자.
package operator;
public class OperationEx5 {
public static void main(String[] args) {
int num = 0B00000101; // 5를 8비트 2진수로 나타냄
System.out.println(num << 2); // 왼쪽으로 2비트 이동 00010100 (20)
System.out.println(num >> 2); // 오른쪽으로 2비트 이동 00000001 (1)
System.out.println(num >>> 2); // 오른쪽으로 2비트 이동 00000001 (1)
System.out.println(num);
num = num << 2;
System.out.println(num);
}
}
여기서 주의할 점은 비트를 이동했다고 해서 num 값이 바로 변하는 것은 아니라는 것이다.
num 값 자체를 변환시켜야만 num의 값이 달라진다.
4. 연산자 우선 순위
1) 단항 연산자가 가장 높고 이항, 삼항 연산자 순서이다.
2) 대입 연산자의 우선순위가 가장 낮다.
3) 산술, 관계, 논리, 대입 연산자 순서로 우선순위를 가지며 ()의 우선순위가 가장 높다.
우선순위 | 형 | 연산자 | 연산 방향 |
1 | 일차식 | () [] | → |
2 | 단항 | ! ++ -- + - | ← |
3 | 산술 | * / % | → |
4 | 산술 | + = | → |
5 | 비트 이동 | << >> >>> | → |
6 | 관계 | < > <= >= | → |
7 | 관계 | == != | → |
8 | 비트 곱 | & | → |
9 | 비트 차 | ^ | → |
10 | 비트 합 | | | → |
11 | 논리 곱 | && | → |
12 | 논리 합 | || | → |
13 | 조건 | ? : | → |
14 | 대입 | = += -= *= %= /= | ← |
'⁂ Java > : 독학으로 공부하기(과거)' 카테고리의 다른 글
[java] #3-2 반복문 : 제어 흐름 이해하기 (0) | 2022.07.03 |
---|---|
[java] #3-1 조건문 : 제어 흐름 이해하기 (0) | 2022.07.01 |
[java] #2-1 자바의 기본 연산자 (0) | 2022.06.30 |
[java] #1-3 상수와 리터럴 (0) | 2022.06.30 |
[java] #1-2 변수와 자료형 (0) | 2022.06.29 |