비트(bit) 단위 연산
이 글은 제가 과거에 운영했던 사이트인 http://dotnet.mkexdev.net 의 글을 옮겨온 것입니다. 원본 글은 2008년 5월에 작성되었습니다.
그 전에 운영했었던 사이트(mkex.pe.kr)은 흔적도 없이 사라 졌습니다. 그속의 글들도 모두... 그래서 이 사이트도 사라지기 전에 옮기고 싶은 글을 조금씩 이 블로그로 이동시키려 합니다.
(원본글) http://dotnet.mkexdev.net/Article/Content.aspx?parentCategoryID=2&categoryID=9&ID=101
정보의 최소 단위는 비트(bit)입니다.
보통 프로그램을 작성할때 int,long 등 바이트(byte) 단위롤 연산하도록 프로그램을 작성합니다.
그러나 비트 단위로 연산을 하게 되면 메모리 공간을 줄이고 성능을 향상 시킬 수 있습니다.
주로 하드웨어 프로그래밍에서 자주 사용되는 연산이라 할 수 있습니다.
그러나 의지만 있으면 우리가 작성하는 일반적인(?) 프로그램도 비트 단위 연산을 하면 성능에 아주 좋은 영향을
줍니다. 지금부터 비트 단위로 연산을 하는 방법을 알아 봅니다.
비트 단위 연산에는 아래와 같은 연산자가 있습니다.
& : 비트 단위 AND
| : 비트 단위 OR
^ : 비트 단위 XOR
~ : 비트 단위 NOT
<< : 왼쪽으로 이동
>> : 오른쪽으로 이동
주의 할 점은 비트 단위 연산에서의 피 연산자, 즉 연산의 대상은 반드시 정수이어야 합니다.
실수의 비트 연산은 불가능 합니다.
& (비트 단위 AND) 연산자
두 비트의 값이 모두 1일때 1을 반환합니다.
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
ex> 15 & 20 연산은 아래와 같이 수행 됩니다.
00001111
& 00010100
-----------------
00000100 = 4 가 됩니다.
| (비트 단위 OR) 연산자
두 비트 중 하나만 1이면 1을 반환합니다.
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
ex> 15 | 20 연산은 아래와 같이 수행 됩니다.
00001111
| 00010100
-----------------
00011111 = 31 가 됩니다.
^ (비트 단위 XOR) 연산자
두 비트가 서로 다를 경우 1을 반환 합니다.
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
ex> 15 ^ 20 연산은 아래와 같이 수행 됩니다.
00001111
^ 00010100
-----------------
00011011 = 27가 됩니다.
~ (비트 단위 NOT) 연산자
비트를 반전 시킵니다(비트 값의 보수)
~ 0 = 1
~ 1 = 0
ex > ~15 연산은 아래와 같이 수행 됩니다.
NOT 00000000 00000000 00000000 00001111
-------------------------------------------------------------------
11111111 11111111 11111111 11110000 가 됩니다.
부호 비트 까지 반전이 되었으므로 음의 정수 값이 됩니다. (15의 1의 보수가 됩니다)
그리고 1을 더하면(결국 15의 2의 보수) -15가 됩니다
<< 왼쪽 쉬프트 (비트 단위 이동) 연산자
a << b => a의 비트들을 b만큼 왼쪽으로 이동합니다.
ex> 15 << 2 연산은 아래와 같이 수행 됩니다.
00000000 00000000 00000000 00001111 을 왼쪽으로 2칸씩 이동 시킵니다.
00000000 00000000 00000000 00001111 데이터 범위를 넘어서 이동한 비트들은 버려집니다(빨간색 부분)
00000000 00000000 00000000 00111100 이동한 만큼 비어 있는 오른쪽 비트는 0으로 채우게 됩니다(빨간색 부분)
따라서 결과는 60 이 됩니다.
주의 할 점은 맨 앞의 부호 비트 까지 이동하므로 데이터의 부호가 바뀔수 있습니다(양/음이 바뀐다)
>> 오른쪽 쉬프트 (비트 단위 이동) 연산자
a << b => a의 비트들을 b만큼 오른쪽으로 이동합니다.
ex>
위의 식에서 a가 양수이면(부호 비트 0) 위의 왼쪽 쉬프트 연산과 완전 동일합니다. 오른쪽으로 넘어간 비트들은 여전히 버려질 것이며 이동한 만큼 비어 있는 왼쪽 비트는 0으로 채우게 될 것입니다.
그러나 a가 음수라면 예기는 좀 달라 집니다.
-10 >> 2 연산은 아래와 같이 수행 됩니다. (2바이트로 표현한다고 가정 합니다)
11111111 11110110 (-10의 2진수 표현) 을 오른쪽으로 2칸씩 이동 시킵니다
11111111 11110110 데이터 범위를 넘어서 이동한 비트들은 버려집니다(빨간색 부분)
??111111 11111101 이동한 만큼 비어 있는 왼쪽 비트는 0 또는 1로 채워 집니다.
시스템에 따라 ?? 부분이 0으로 채워질 수도 1로 채워질 수도 있습니다.
음수를 유지하기 위해 1로 채우기도 하고, 양수의 비트 연산처럼 0으로 채우기도 합니다.
해당하는 시스템을 확인 할 필요가 있습니다.
Tip>>
<< (왼쪽 쉬프트) 연산을 사용하면 주어진 값의 배수를 쉽게(빠르게) 구할 수 있다.
<< 연산자를 이용하여 1칸씩 왼쪽으로 이동하면 계속해서 값의 2배가 된다.
ex> 15 << 1 = 30 , 15 << 2 = 60 .....
같은 의미로 >> (오른쪽 쉬프트) 연산을 사용하면 주어진 값을 2로 나눈 결과가 나온다.
>> 연산자를 이용하여 1칸씩 오른쪽으로이동하면 계속해서 값을 2로 나눈 결과가 나온다
단, 나눈 결과가 실수 이면 소수점 부분은 제외(절사) 된다.
ex> 30 >> 1 = 15 , 30 >> 2 = 7 , 30 >> 3 = 3
정수값의 부호를 바꾸고 싶으면 2의 보수를 사용하면 된다.
즉, 이 말은 정수값의 ~(NOT) : 1의 보수 값을 구해서 1을 더하면 2의 보수가 되는 원리를 이용하면 된다.
ex> (~-100) + 1 = 100