부호비트 및 2의 보수, 2진수 알면 내용 이해가 편하다
https://seungmin576.tistory.com/3
비트 연산자
말 그대로 비트 단위로 연산이 이루어지는 연산자이다.
- 비트 단위의 연산을 하는 경우
1. '암호화' 작업처럼 임의의 숫자를 만들때.
2. 어떤 변수의 특정 비트를 꺼내보는 마스킹(masking) 경우에 사용한다.
3.하드웨어에 내장되는 임베디드 시스템 프로그램에서 메모리 용량이 부족하거나 계산이 복잡해서 속도가 느려질 때, 곱셈이나 나눗셈을 비트 이동 연산자를 사용하면 어떤 수의 2배수, 4배수를 만들어 속도를 빠르게 할 수 있다.
자바는 이런 환경은 아니지만 프로그램에서 특정 값을 만들거나 연산할 때 비트 연산자를 사용한다.
- 비트 논리 연산자
비트 단위로 &, |, ^, ~ 연산이 이루어 진다.
&연산자
두 개의 비트 값이 모두 1인 경우에만 연산의 결과 값이 1이 된다.
int num1 = 5;
int num2 = 10;
int result = num1 & num2;
num1 : 00000101
num2 : 00001010
------------------
result : 00000000
위 경우엔 2진수로 바꿔보면 5는 00000101, 10은 00001010 이기 때문에 result는 0이다.
|연산자
|(OR) 연산자는 비트 값이 하나라도 1이면 연산 결과 값이 1이 된다.
int num1 = 5;
int num2 = 10;
int result = num1 | num2;
num1 : 00000101
num2 : 00001010
------------------
result : 00001111
result는 00001111이다. 10진수 변환하면 15이다.
^연산자
^(XOR) 연산자는 같은 값이면 0, 다른 값이면 1의 결과 값을 갖는다.
int num1 = 5;
int num2 = 10;
int result = num1 ^ num2;
num1 : 00000101
num2 : 00001010
------------------
result : 00001111
result는 00001111이다. 10진수 변환하면 15이다.
~연산자
~(반전) 연산자는 비트 값을 0은 1로, 1은 0으로 바꾸는 연산자이다.
int num = 10;
int result = ~num;
num : 00001010
------------------
~num : 11110101
//이건 ~num이 몇인지 알아내는 방법
~num : 11110101
2의 보수: 00001011
-------------------
결과 : 00000000
2의 보수 10진수화 = 11
~num= -11
위 경우는 부호비트가 1로 바뀌기 때문에 음수로 바뀐다.
양수로 다시 변환해야 값이 얼마인지 알 수 있다. (2진수에서는 2의보수가 음수이다.)
2진수 11110101을 10진수로 변환하면 11이 되고 ~num의 값은 -11이다.
- 비트 이동 연산자
<<, >>, >>> 세가지가 있다.
이를 시프트(shift) 연산자라고도 부른다.
<< 연산자
<< 시프트 연산자는 왼쪽으로 비트를 이동하는 연산자이다.
int num = 5;
num << 2;
num : 00000101
num << 2 : 00010100
00000101을 두 비트만큼 왼쪽으로 이동했다.
이때 앞 두자리 비트 00은 없어지고 뒷부분은 0으로 채워진다.
왼쪽으로 n비트 이동한다는 것은 기존 값에 2n만큼 곱한다는 뜻이다.
(이런식으로 2의 배수 곱할땐 산술 연산자인 *연산자 사용보다 시프트 연산자인 <<연산자가 성능이 좋다.
나중에 성능까지 생각해야되는 고수의 단계라면 시프트 연산자를 이용한 곱셈으로 프로그래밍하는 것도 좋을 것 같다.)
따라서 5* 22 = 20 이다.
>> 연산자
>> 시프트 연산자는 오른쪽으로 비트를 이동하는 연산자이다.
int num = 10;
num >> 2;
num : 00001010
num >> 2 : 00000010
오른쪽으로 n비트 이동하면 기존 값을 2n만큼 나눈다.
위 경우 10/22이 되므로 결과 값은 2가 된다.
위 경우 왼쪽에 채워지는 비트 값은 기존 값의 부호 비트와 동일하다.
>>> 연산자
>>> 시프트 연산자는 >> 연산과 동일하게 비트를 오른쪽으로 이동한다.
차이가 있다면 >>> 연산자는 왼쪽에 채워지는 비트 값이 부호 비트에 상관없이 무조건 0이 된다
public class OperationEx3 {
public static void main(String[] args){
int num = 0B00000101;
System.out.println(num << 2);
System.out.println(num >> 2);
System.out.println(num >>> 2);
System.out.println(num);
num <<= 2;
System.out.println(num);
}
}

비트를 이동한다고 해서 바로 num값이 변하지는 않는다.
왜냐하면 num 값을 참조해서 이동했을 뿐 이동한 값을 num에 대입하지 않았기 때문이다.
따라서 9행에서 num값은 비트 이동과 관계없이 5가 된다.
10행처럼 결과 값을 직접 num에 대입해 주어야 num값이 바뀐다.
연산자 우선순위
- 단항 연산자가 가장 높고 이항, 삼항 연산자 순서이다.
- 대입 연사자의 우선순위가 가장 낮다.
- 산술, 관계, 논리, 대입 연산자 순서로 우선순위를 가지며 ()의 우선순위가 가장 높다.
| 우선순위 | 형 | 연산자 | 연산 방향 |
| 1 | 일차식 | () [] . | -------⫸ |
| 2 | 단항 | ! ++ -- + - | ⫷-------- |
| 3 | 산술 | % / | -------⫸ |
| 4 | 산술 | + - | -------⫸ |
| 5 | 비트 이동 | << >> | -------⫸ |
| 6 | 관계 | < > <= >= | -------⫸ |
| 7 | 관계 | == != | -------⫸ |
| 8 | 비트 곱 | & | -------⫸ |
| 9 | 비트 차 | ^ | -------⫸ |
| 10 | 비트 합 | | | -------⫸ |
| 11 | 논리 곱 | && | -------⫸ |
| 12 | 논리 합 | || | -------⫸ |
| 13 | 조건 | ?: | -------⫸ |
| 14 | 대입 | = += -= *= %= /= | ⫷-------- |