비트연산
비트연산은 컴퓨터 과학에서 기본 연산으로 주로 알고리즘 문제 해결에서 자주 등장하지만, 실무에서는 권한 관리나 시스템 최적화, 네트워킹 등의 특수한 상황에서만 중요한 역할을 합니다.
비트연산자는 두 이진수(0과 1로 구성된 숫자)에 대해 비트 단위로 논리 연산을 수행합니다. 이러한 연산자에는 주로 AND(&), OR(|), XOR(^), NOT(~), 비트 시프트(<<, >>) 등이 있습니다.
비트연산자를 사용할 때의 일반적인 흐름은 다음과 같습니다.
- 10진수를 2진수로 변환: 컴퓨터는 내부적으로 모든 데이터를 이진수로 처리하기 때문에, 비트 연산을 수행하기 전에 먼저 관련 데이터를 이진수 형태로 변환합니다.
- 2진수에서 비트연산을 전개: 변환된 이진수에 대해 원하는 비트연산을 수행합니다. 예를 들어, 두 숫자에 대해 비트 AND 연산을 수행하면, 두 이진수 모두에서 1인 비트 위치에서만 결과가 1이 되는 새로운 이진수를 얻게 됩니다.
- 2진수를 10진수로 변환: 연산 결과로 나온 이진수를 다시 10진수로 변환하여 사용합니다. 이 과정은 연산 결과를 사람이 이해하기 쉬운 형태로 만들거나, 다른 10진수 기반의 연산이나 처리와 호환될 수 있도록 합니다.
비트연산의 개념과 흐름을 이해하는 것은 컴퓨터 프로그래밍의 깊이를 더하는 데 중요합니다. 이를 통해 더 효율적이고, 최적화된 코드를 작성할 수 있는 능력을 키울 수 있습니다.
1. 비트 and(&) 연산자
비트 and
연산자 &
는 두 비트열의 동일한 위치에 있는 비트가 모두 1일 경우에만 결과로 1을 반환하는 연산자입니다. 이 연산자는 주로 비트 레벨에서 데이터의 특정 부분을 마스킹하는데 사용됩니다.
예를 들어, 아래의 예제에서는 두 수 60과 13에 대해 비트 AND 연산을 수행합니다.
이 연산의 계산 과정은 다음과 같습니다:
- 이진수 변환: 먼저, a의 값인 60과 b의 값인 13을 이진수로 변환합니다.
- 60의 이진수:
0011 1100
- 13의 이진수:
0000 1101
- 60의 이진수:
- 비트 AND 연산: 각 위치의 비트를 비교하여 두 비트 모두 1일 경우에만 결과의 해당 위치에 1을 배치합니다.
0011 1100
(60의 이진수)0000 1101
(13의 이진수)0000 1100
(AND 연산 결과)
- 결과의 이진수를 10진수로 변환: 연산 결과인
0000 1100
을 10진수로 변환합니다. 이 값은 12입니다.
이처럼 비트 AND 연산자는 각 비트 위치에 대해 논리적 'AND' 연산을 수행하여, 두 입력값이 모두 1인 경우에만 결과로 1을 반환합니다.
위 내용을 코드 블록으로 요약한 것입니다.
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# b의 값 13을 2진수로 풀어줍니다.
0000 1101
# 위아래로 AND 연산을 수행합니다.
0011 1100
0000 1101
# & 연산의 경우 위와 아래 한짝씩 맞춰 and 연산을 수행합니다.
# 이때 1 = True, 0 = False 입니다.
0011 1100
0000 1101
---------
0000 1100
# 결과값을 다시 10진수로 변환합니다.
12
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# b의 값 13을 2진수로 풀어줍니다.
0000 1101
# 위아래로 AND 연산을 수행합니다.
0011 1100
0000 1101
# & 연산의 경우 위와 아래 한짝씩 맞춰 and 연산을 수행합니다.
# 이때 1 = True, 0 = False 입니다.
0011 1100
0000 1101
---------
0000 1100
# 결과값을 다시 10진수로 변환합니다.
12
2. 비트 or(|) 연산자
비트 or
연산자 |
는 두 비트열의 동일한 위치에 최소 하나의 비트가 1일 경우 결과로 1을 반환합니다. 이 연산자는 특정 비트를 설정하거나 두 값 중 하나라도 1인 비트를 확인할 때 유용합니다.
아래 예시에서는 두 수 60과 13에 대해 비트 OR 연산을 수행합니다.
이 연산의 과정은 다음과 같습니다:
- 이진수 변환: 먼저, a와 b의 값인 60과 13을 이진수로 변환합니다.
- 60의 이진수:
0011 1100
- 13의 이진수:
0000 1101
- 60의 이진수:
- 비트 OR 연산: 각 위치의 비트를 비교하여 두 비트 중 하나라도 1이면 결과의 해당 위치에 1을 배치합니다.
0011 1100
(60의 이진수)0000 1101
(13의 이진수)0011 1101
(OR 연산 결과)
- 결과의 이진수를 10진수로 변환: 연산 결과인
0011 1101
을 10진수로 변환합니다. 이 값은 61입니다.
비트 OR 연산자는 데이터의 특정 비트를 '켜기' 위한 설정이나, 여러 조건 중 하나라도 충족하는지 확인할 때 주로 사용됩니다. 예를 들어, 사용자 권한 설정에서 여러 권한 중 하나라도 부여되어야 하는 경우 비트 OR 연산을 통해 이를 쉽게 구현할 수 있습니다.
위 내용을 코드 블록으로 요약한 것입니다.
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# b의 값 13을 2진수로 풀어줍니다.
0000 1101
# 위아래로 붙여보겠습니다.
0011 1100
0000 1101
# 연산의 경우 위와 아래 한짝씩 맞춰 or 비교를 해봅니다.
# 이때 1 = True, 0 = False 입니다.
0011 1100
0000 1101
---------
0011 1101
# 결과값을 다시 10진수로 변환해줍니다.
61
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# b의 값 13을 2진수로 풀어줍니다.
0000 1101
# 위아래로 붙여보겠습니다.
0011 1100
0000 1101
# 연산의 경우 위와 아래 한짝씩 맞춰 or 비교를 해봅니다.
# 이때 1 = True, 0 = False 입니다.
0011 1100
0000 1101
---------
0011 1101
# 결과값을 다시 10진수로 변환해줍니다.
61
3. 비트 xor(^) 연산자
비트 xor
연산자 ^
는 두 비트열의 동일한 위치에 있는 비트가 서로 다를 경우에만 1을 반환합니다. 이 연산자는 비교되는 두 값이 다를 때 사용되며, 암호화, 오류 검출, 값의 토글 등 다양한 상황에서 사용됩니다.
다음은 두 수 60과 13에 대해 비트 XOR 연산을 수행하는 예시입니다.
이 연산의 과정은 다음과 같습니다:
- 이진수 변환: 먼저, a와 b의 값인 60과 13을 이진수로 변환합니다.
- 60의 이진수:
0011 1100
- 13의 이진수:
0000 1101
- 60의 이진수:
- 비트 XOR 연산: 각 위치의 비트를 비교하여 서로 다를 경우(하나는 1, 다른 하나는 0) 결과의 해당 위치에 1을 배치합니다.
0011 1100
(60의 이진수)0000 1101
(13의 이진수)0011 0001
(XOR 연산 결과)
- 결과의 이진수를 10진수로 변환: 연산 결과인
0011 0001
을 10진수로 변환합니다. 이 값은 49입니다.
비트 XOR 연산자는 두 값이 서로 다른 경우를 찾을 때 사용됩니다. 예를 들어, 두 데이터 집합에서 변경된 부분을 찾거나, 데이터를 암호화 및 복호화하는 데 사용할 수 있습니다. 또한, 같은 값을 두 번 XOR 연산하면 원래 값으로 돌아오는 성질을 가지고 있어, 데이터의 일시적인 저장과 복원에도 사용됩니다.
위 내용을 코드 블록으로 요약한 것입니다.
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# b의 값 13을 2진수로 풀어줍니다.
0000 1101
# 위아래로 붙여보겠습니다.
0011 1100
0000 1101
# 연산의 경우 위와 아래 한짝씩 맞춰 xor 비교를 해봅니다.
# 이때 1 = True, 0 = False 입니다.
0011 1100
0000 1101
---------
0011 0001
# 결과값을 다시 10진수로 변환해줍니다.
69
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# b의 값 13을 2진수로 풀어줍니다.
0000 1101
# 위아래로 붙여보겠습니다.
0011 1100
0000 1101
# 연산의 경우 위와 아래 한짝씩 맞춰 xor 비교를 해봅니다.
# 이때 1 = True, 0 = False 입니다.
0011 1100
0000 1101
---------
0011 0001
# 결과값을 다시 10진수로 변환해줍니다.
69
4. 비트 not(~) 연산자
비트 not
연산자 ~
는 주어진 비트열의 모든 비트를 반전시키는 연산자입니다. 이 연산자는 1을 0으로, 0을 1로 바꿉니다. 비트 NOT 연산은 종종 데이터의 비트 패턴을 전환하거나, 특정 비트를 '끄는' 데 사용됩니다.
아래 예시에서는 수 60에 대해 비트 NOT 연산을 수행합니다.
이 연산의 과정은 다음과 같습니다:
- 이진수 변환: 먼저, a의 값인 60을 이진수로 변환합니다.
- 60의 이진수:
0011 1100
- 60의 이진수:
- 비트 NOT 연산: 모든 비트를 반전시킵니다. 1은 0으로, 0은 1로 바뀝니다.
0011 1100
(60의 이진수)-------
1100 0011
(NOT 연산 결과)
- 결과의 이진수를 10진수로 변환: 연산 결과인
1100 0011
을 10진수로 변환합니다. 이 경우, 결과는 -61입니다.
여기서 중요한 점은, 대부분의 컴퓨터 시스템에서 정수는 2의 보수 형태로 표현된다는 것입니다. 따라서, 비트 NOT 연산 후의 결과는 원래 수의 음의 값에서 1을 뺀 값이 됩니다. 예를 들어, ~60
의 결과는 -61
이 됩니다. 이는 60
을 2진수로 표현하고 모든 비트를 반전시킨 후, 이 결과를 2의 보수 형태로 음의 정수로 해석하기 때문입니다.
위 내용을 코드 블록으로 요약한 것입니다.
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# 연산의 경우 부정을 취합니다.
0011 1100
----
1100 0011
# 결과값을 다시 10진수로 변환해줍니다.
-61
# a의 값 60을 2진수로 풀어줍니다.
0011 1100
# 연산의 경우 부정을 취합니다.
0011 1100
----
1100 0011
# 결과값을 다시 10진수로 변환해줍니다.
-61
5. 비트 shift 연산자
비트 Shift 연산자는 비트열을 왼쪽 또는 오른쪽으로 이동시키는 연산자입니다. 이 연산자는 데이터의 이진 표현을 효율적으로 조작하고, 곱셈 및 나눗셈 연산을 빠르게 수행하는 데 유용합니다.
- 왼쪽 시프트 연산자(<<): 비트열을 왼쪽으로 이동시키며, 오른쪽 끝에 빈 자리는 0으로 채워집니다. 왼쪽 시프트 연산은 주어진 비트 수만큼 2의 거듭제곱을 곱하는 것과 동일합니다.
- 오른쪽 시프트 연산자(>>): 비트열을 오른쪽으로 이동시키며, 왼쪽 끝에 빈 자리는 0(부호가 없는 정수) 또는 부호 비트(부호가 있는 정수)로 채워집니다. 오른쪽 시프트 연산은 주어진 비트 수만큼 2의 거듭제곱으로 나누는 것과 동일합니다.
이제, 숫자 7에 대해 왼쪽 Shift 연산을 수행하는 예를 살펴보겠습니다.
입력
계산 과정은 다음과 같습니다:
- 이진수 변환: a의 값인 7을 이진수로 변환합니다.
- 7의 이진수:
0111
- 7의 이진수:
- Shift 연산: a의 비트열을 왼쪽으로 b(2)만큼 이동시킵니다. 오른쪽 끝의 빈 자리는 0으로 채워집니다.
0111
(7의 이진수)1 1100
(왼쪽 Shift 연산 결과)
- 결과의 이진수를 10진수로 변환: 연산 결과인
1 1100
을 10진수로 변환합니다. 이 값은 28입니다.
위 내용을 코드 블록으로 요약한 것입니다.
# a의 값 3을 2진수로 바꿉니다.
0111
# b 만큼 이동할 것이기 때문에 b는 바꾸지 않음
# a의 값들(집합)을 왼쪽으로 b만큼 이동시키고 뒤에 0을 붙임
011100
# 결과 값을 10진수로 다시 변환합니다.
28
# a의 값 3을 2진수로 바꿉니다.
0111
# b 만큼 이동할 것이기 때문에 b는 바꾸지 않음
# a의 값들(집합)을 왼쪽으로 b만큼 이동시키고 뒤에 0을 붙임
011100
# 결과 값을 10진수로 다시 변환합니다.
28
6. 2의 보수
2의 보수는 컴퓨터 시스템에서 음수를 표현하는 데 주로 사용되는 방법입니다. 이 방식을 사용하면 덧셈, 뺄셈과 같은 연산이 간단해지며, 음수와 양수 사이의 전환도 쉽게 할 수 있습니다.
예를 들어, 숫자 40의 2의 보수를 구하는 과정은 다음과 같습니다.
a = 40
~a #bit NOT(2의 보수)
101000
#비트단위를 뒤짚었습니다.
010111
#비트단위를 뒤짚고 +1했습니다.
011000
101000
011000
000000 #자기 자신와 보수의 값을 더하면 값은 0이 나옵니다.
#1. 0을 2개로 표현하지 않아도 됩니다.
#2. 값을 더했을 경우 올림수 하나만 버리면 됩니다.
a = 40
~a #bit NOT(2의 보수)
101000
#비트단위를 뒤짚었습니다.
010111
#비트단위를 뒤짚고 +1했습니다.
011000
101000
011000
000000 #자기 자신와 보수의 값을 더하면 값은 0이 나옵니다.
#1. 0을 2개로 표현하지 않아도 됩니다.
#2. 값을 더했을 경우 올림수 하나만 버리면 됩니다.
1의 보수는 비트를 완전히 뒤집는 방법입니다. 하지만, 이 방법을 사용하면 -0과 +0의 문제가 발생합니다. 대부분의 현대 컴퓨터 시스템은 2의 보수 방식을 사용합니다. 이 방식에서는 0을 00000000
로 표현하고, 1부터는 비트 단위 보수를 취한 후 +1을 더합니다. 2의 보수를 사용하면 오버플로우가 발생하여 절대값이 같은 음수와 양수를 더했을 때 결과가 0이 되는 특성이 있습니다.