본문 바로가기

프로그래밍/javascript(ES)

자바스크립트 비트 연산자

자바스크립트는 모든 것이 다 10진수 단위로 처리되며, 2진수 처리를 보기는 힘듭니다. 사실 저도 2진수 단위에서까지 처리를 하고 계산하는 코드를 별로 짜고 싶어 하지 않을 뿐더러.. 성능 문제가 심각하지 않다면 일반적 숫자 개념만 있어도 충분히 프로그램을 짤 수 있고 하기 때문에 지금까지 영 많이 쓰지는 않았습니다.

일단 사용할 이유가 별로 많지 않기 때문이죠. 이렇게 보다보면 JS에 2진수 처리가 있긴 한걸까 생각할만도 한데.. 그렇다고 2진수 처리가 없는 것은 아니랍니다. 생각보다 JS에는 여러가지 비트 연산자들이 있는었습니다. 간단한 논리 비트 연산자부터 비트를 몇칸씩 움직이는 연산자, 그리고 비트들의 값을 뒤집어버리는 연산자도 있답니다. 물론 이런 연산자들이 무한한 2진수에서 계산을 하는 것은 아니고, 32bit int를 기준으로 계산합니다.

그럼, 이런 연산자들에 대해 배워보도록 합시다. ( 2진수와 32비트 int의 구조에 대해서 알면 더 유익하고 편하게 읽을 수 있습니다. 2진수 개념 관련 글, 32비트 int 관련 글)




& AND 논리 연산자

우리가 보통 많이 썼던 && AND 연산자가 생각나지 않나요? 그렇습니다. 2진 연산자에서도 마찬가지로 AND 연산자가 존재하는데요. 우리가 보통 true / false를 이용해 연산하는 AND 연산자는 "&&" 이렇게 사용하지만 2진 AND 연산자는 그냥 "&" 하나면 된답니다. 그러면, 2진수 구조에서는 어떻게 AND가 계산되는 것일까요?


이진수 계산은 위와 같이 이루어집니다. 먼저 10 & 12 에서 10은 이진수로 1010, 12는 이진수로 1100. 이렇게 바꾸어 줍니다. 그리고, 두 숫자에서 자리가 둘다 1인 부분만 걸러 줍니다.

자리에서 둘다 1이 들어간 부분만 1로 처리합니다. 그렇게 걸러내고 나면 결과가 나오겠죠? 그런 다음에는 JS가 10진수를 기본으로 사용하니 다시 10진수로 합체를 해 줍니다. 1000은 십진수로 8이니, 실행결과는 8이 되는 것이죠.


이런식으로 실행됩니다.


| OR 논리 연산자

AND 연산자가 나왔다면 이번에는 OR 연산자가 나올 차례입니다. 이 OR 연산자도 우리가 흔히 봤던 "||" 와는 다르게, "|" 하나만으로 작동합니다. 그럼, 2진수에서는 OR이 어떻게 작동할까요?


OR 또한 AND처럼 2진수 단위에서 무언가 처리해주는데요. 이번에는 둘다 1이 있는 곳만 걸러주는 것이 아닌, 어디가 1이던 다 '포함' 해 줍니다. 둘중 하나라도 1이 있다면 그 비트의 값은 1로 지정됩니다. 실행 방식이 평소에 썼던 "||" 같죠?


이런식으로 작동합니다.


^ 배타 논리 연산자

해당 연산자는 보통 잘 사용하지 않고 보지도 못했을 것입니다. 조금 특이한 성질을 가지고 있는 연산자인데요. 바로, 두개의 비트가 같으면 0을, 다르면 1을 반환하는 아주 신기한 성질을 가지고 있습니다. 그럼, 어떤 식으로 작동하는지 알아봅시다.


각각의 비트들에 대해서 체크를 합니다. 두 비트가 같은 값을 가지고 있는지 말이죠. 만약에 비트의 값이 같으면 그 자리에는 0을 넣고, 같지 않을 경우에는 그 자리에 1을 넣습니다.

만약에 10과 12를 이용하여 계산하였다면, 이런식으로, 6이 나옵니다.


~ 부정 논리 연산자

부정 논리 연산자는 특이하게, 피연산자(대상이 되는 수)가 1개밖에 들어가지 않습니다. '부정' 하면 떠오르는 연산자, "!" 처럼 말이죠. 이 연산자의 역할도 '!' 연산자와 비슷한데요. 각 비트들의 값을 뒤집어 버립니다. 모두다 말이죠.

비트들의 값을 모두 뒤집어 버리면, 이런식으로 숫자의 음/양이 바뀌어 버립니다. 왜냐하면, JS는 비트 단위 연산을 할 경우에 32비트 int를 기준으로 연산을 하기 때문이죠. 32비트 int에서는 가장 앞 비트가 -2147483648을 나타냅니다. ( 32비트 INT )

이런식으로 작동합니다.


>> , << 일반적 시프트

이제부터는 두 값을 비교하거나 비트 단위에서 뒤집는 것을 하는 연산자는 아닌, 비트들을 밀어주는 연산자입니다. 시프트 연산자들은 모두 비트를 몇칸씩 밀어주는 역할을 하는데요. 10진수에서 굳이 따지자면 곱하기 10 이나 나누기 10 정도의 역할을 해 주는 연산자들입니다.


그럼, 먼저 왼쪽 시프트 연산자를 알아봅시다.



먼저, 왼쪽 시프트 연산자는 "수 << 칸수" 로 사용할 수 있습니다.

15 에서 비트 단위로 2칸을 밀어 주면, 기존에 "1111" 이었던 비트들이 2칸 왼쪽으로 밀리면서 "11 1100" 이 됩니다. 이러면 15는 60이 되죠. 여기서 규칙을 아마 눈치채신 분들이 있을 것입니다. 2진수이기 때문에, 몇칸 미냐에 따라서 2의 제곱 만큼 수가 곱해지기 때문이죠.

우리 10진수에서 15를 두칸 왼쪽으로 밀면 1500 이 됩니다. 1500은 15에 어떤 연산을 해야 만들어질까요? 15*(10*10) 이죠. 이와 같이 2진수에서도 이런 규칙이 적용됩니다. 15에서 만약 4칸을 민다면, 15*(2*2*2*2) 가 되겠죠? 그렇게 되면 240이 나옵니다. 이런 계산을 이용하면, 제곱을 간단히 할 수도 있습니다.


다음으로는 오른쪽 시프트 연산자 입니다.


왼쪽 시프트 연산자는 수를 점점 0에서 멀리 떨어지도록 만듭니다. 오른쪽 시프트 연산자는 거꾸로, 0으로 점점 가까워지게 만듭니다. 왜냐하면, 비트들을 오른쪽으로 미는 기능을 가지고 있기 때문이죠.

위와 같이 비트들을 오른쪽으로 미는데요. 오른쪽으로 밀 때에 가장 왼쪽에는 기존에 있던 첫번째 비트가 오고, 가장 오른쪽에 있던 비트들은 소멸되어 버린답니다. 그렇기에 오른쪽 시프트 연산자는 2배, 4배 같은 규칙성을 찾아볼 수는 없습니다.


>>> , 특이한 오른쪽 쉬프트

오른쪽 쉬프트이긴 한테 특이하다니, 무슨 소리일까요? 한칸을 밀 때마다 0이 왼쪽에 하나씩 붙기 때문입니다. 원래 그런 거 아니냐 라고 할수도 있지만, 위에 설명을 잘 읽어보면.. 첫번째 비트를 왼쪽에 넣는다고 설명되어 있습니다. 음수에서는 맨 왼쪽에 있는 양/음수 제어 비트를 그대로 두어야 -4, -2 이런식으로 쉬프트될수 있기 때문입니다.


위에서 봤던 일반적인 쉬프트 연산자들과는 다릅니다. 맨 왼쪽에 비트가 음의 끝 수를 의미하는데 그곳이 깨져버리니 완전히 다른 수가 나와버립니다. 위 사진처럼 밀고 나면, 왼쪽에 0이 붙습니다.




이번 글에서는 자바스크립트 에서의 비트 연산자에 대해 알아보았는데요. 쉬프트 연산자나 AND, OR 같은 연산자들은 가끔 쓸일이 있을 것 같으니 잘 기억해둡시다. 그럼 글은 여기에서 마치고 이만!