팀원들과 함께하는 모던 JS 딥다이브 스터디 2차 💕
비트연산자
는 피연산자를 32비트 정수로 변환해 이진 연산을 수행 후 십진수로 바꿔 반환한다.
JS는 모든 숫자를 64비트 부동소수점 방식으로 저장하지만,
비트연산을 수행할 땐 32비트 정수로 변환 해 연산 수행 후 다시 64비트로 변환해 저장한다.
⚠️ 32비트 정수로 변환했을 때 초과한다면 최상위 비트를 버린다.
11100110111110100000000000000110000000000001 // 30274560
10100000000000000110000000000001 // 20971712
&
)|
)^
)~
)<<
)>>
)>>>
)&
)const a = 5; // 00000000000000000000000000000101 (0101)
const b = 3; // 00000000000000000000000000000011 (0011)
console.log(a & b) // 0001 = 1
비교 대상인 두 비트가 1이면 1을 반환한다. 두 비트가 다를 경우 0을 반환한다.
12 & 15 // 1100 & 1111 = 1100 = 12
|
)const a = 5; // 00000000000000000000000000000101 (0101)
const b = 3; // 00000000000000000000000000000011 (0011)
console.log(a | b) // 0101 | 0011 = 0111
비교 대상인 두 비트 중 하나라도 1이면 1을 반환한다. 둘다 0이면 0을 반환한다.
console.log(12 | 15) // 1100 | 1111 = 1111 = 15
^
)const a = 5; // 00000000000000000000000000000101 (0101)
const b = 3; // 00000000000000000000000000000011 (0011)
console.log(a | b) // 0101 | 0011 = 0110 = 6
비교 대상인 두 비트가 같으면 0을, 다르면 1을 반환한다.
console.log(12 | 15) // 1100 & 1111
~
) ⭐️const a = 5; // 00000000000000000000000000000101 (0101)
const b = 3; // 00000000000000000000000000000011 (0011)
console.log(~a) //
// 00000000000000000000000000000010
// 11111111111111111111111111111010 //
피연산자를 2의 보수 형식으로 부호가 있는 32비트 정수로 변환한다.
컴퓨터에는 음수란 개념이 없다. 따라서 보수라는 것을 쓴다.
보수
: 보충해주는 수
ex) 1에 대한 10의 보수: -9
ex) 2에 대한 1의 보수: 1
1. 부호비트방식
최상위비트를 부호비트로 사용하는 방식
최상위비트가 0이면 양수, 1이면 음수
⚠️ 문제점) 2진수의 계산이 힘들어짐
0001 + 1001 = 1010 (-2)
1 + -1 = -2???
2. 1의 보수법
1의 보수
: 음수 표현 시에 0을 1로, 1을 0으로 바꾸는 것
1을 2진수로 표현: 0001
1을 1의 보수로 표현: 1110
0010 + 1110 = 10000 🧐
2 + -1 = 0
// ⚠️ 1의 보수는 overflow 발생 시 캐리값을 결과값에 더해줘야 함.
0010 + 1110 = 0000 + 0001 = 0001
2 + -1 = 1
1101 + 0001 = 1110 ☺️
-2 + 1 = -1
0001 + 1110 = 1111 🧐
1 + -1 = -0
1의 보수는 1111(-0), 0000(+0) 이라는 2개의 0을 갖는다.
3. 2의 보수법
음수표현 시 1의 보수의 문제점을 해결하기 위해 1의 보수에서 1을 더한 것.
0010 + 1111 = 10001 = 0001
2 + -1 = 1
// 최상위비트가 1이지만 무시
1110 + 0001 = 1111
-2 + 1 = -1
1111 + 0001 = 10000 = 0000
-1 + 1 = 0
<<
)두 개의 피연산자를 사용한다.
첫번째 피연산자는 정수,
두번째 피연산자는 왼쪽으로 shift 시킬 비트의 수.
🔥 요약: 왼쪽 시프트 = 왼쪽을 줄임.
const a = 5;
console.log(a << 3)
// 00000000000000000000000000000101 (0101) = 5
// (***)00000000000000000000000000101(000) = 2^5 + 2^3 = 32 + 8 = 40
// ***는 초과되서 버리는 비트
const b = 3; // 00000000000000000000000000000011 (0011)
console.log(b << 2)
// (**)000000000000000000000000000011(00) = 2^3 + 2^2 = 12
>>
)부호비트가 복사되어 늘어남.
부호가 변하지 않으므로 Sign-propagating(부호 유지) right shift
라는 이름이 붙었다. (길어...)
🔥 요약: 오른쪽 시프트 = 오른쪽을 줄임.
const a = 5;
console.log(a >> 3)
// 00000000000000000000000000000101 (0101) = 5
// (000)00000000000000000000000000000(***) = 0
const b = 3; // 00000000000000000000000000000011 (0011)
console.log(b >> 3)
// 00000000000000000000000000000011 (0011)
// (000)00000000000000000000000000000(***) = 0
const c = 150; // 00000000000000000000000010010110 (10010110)
console.log(c >> 3)
// 00000000000000000000000010010110
// (000)00000000000000000000000010010(***) = 18
>>>
)0비트를 부호비트 앞으로 추가함.
const c = 150; // 00000000000000000000000010010110 (10010110)
const minusC = -150; // 11111111111111111111111101101001
console.log(c >> 3)
// 00000000000000000000000010010110
// (000)00000000000000000000000010010(***) = 18
console.log(minusC >>> 3)
// 11111111111111111111111101101001
// 00011111111111111111111111101101(***) = 536870893
MDN | 비트연산자
[JavaScript 33가지 개념] 12. Bitwise Operator(비트 연산자)
연산자 (산술연산자/비트연산자)
1의 보수
2의 보수를 쓰는 이유와 2의 보수법