- ASCII에서 Z는 90, a는 97에 배치되어 있으며, 그 사이 6개 문자 덕분에 대문자와 소문자의 코드 차이가 32로 맞춰짐
- 32는 2^5라서 A 65와 a 97처럼 대응하는 대소문자는 항상 00100000 비트 하나만 다름
- 이 배치 덕분에 32의 비트 반전값과 AND하면 대문자화, 32와 OR하면 소문자화, 32와 XOR하면 대소문자 반전이 가능함
- 알파벳 순번은 문자 코드에 31을 AND해 하위 5비트만 남기면 얻을 수 있으며, A/a는 1, Z/z는 26이 됨
- ASCII는 7비트로 128개 코드 포인트만 표현하는 초기 문자 인코딩이며, 오늘날 쓰이는 Unicode의 첫 128개 코드 포인트는 ASCII와 동일함
ASCII 배치와 32 차이
- ASCII 표에서 대문자 Z의 코드값은 90이고, 소문자 a는 바로 다음 값이 아니라 97에 배치됨
- 그 사이에는 [ \ ] ^ _ `의 6개 문자가 있음
- 영어 알파벳은 26자이고, 이 6개 문자를 더하면 26 + 6 = 32가 됨
- 32는 2^5에 해당하는 값이라, 대문자와 소문자 대응 관계가 특정 비트 하나의 차이로 정렬됨
- 예를 들어 A는 65이자 01000001, a는 97이자 01100001이며, 두 값의 차이는 32임
ASCII와 Unicode의 관계
- ASCII는 초기 문자 인코딩 방식 중 하나이며, 7비트만 사용해 2^7 = 128개의 코드 포인트를 표현함
- 128개 코드 포인트는 사람이 사용하는 모든 문자를 담기에는 부족하며, 특히 수만 개 문자를 가진 중국어 같은 언어까지 담기에는 충분하지 않음
- 오늘날 표준 문자 집합으로는 Unicode가 쓰이며, UTF-8과 UTF-16 같은 여러 인코딩을 가짐
- Unicode의 첫 128개 코드 포인트는 ASCII와 동일함
대소문자를 가르는 5번째 비트
- 대문자와 대응하는 소문자를 이진수로 비교하면 항상 32에 해당하는 비트가 바뀜
65 = 01000001 = A
97 = 01100001 = a
66 = 01000010 = B
98 = 01100010 = b
67 = 01000011 = C
99 = 01100011 = c
- 32는 이진수에서 00100000이며, 이 비트 하나가 대문자와 소문자 차이를 만듦
- ASCII의 알파벳 배치는 비트 연산으로 대소문자 변환을 쉽게 할 수 있게 되어 있음
비트 연산으로 대소문자 처리하기
-
대문자로 변환
- 문자를 대문자로 만들려면 32의 비트 반전값과 비트 AND를 수행함
0 1 1 0 0 0 0 1 (97 = 'a')
& 1 1 0 1 1 1 1 1 (mask)
-------------------
0 1 0 0 0 0 0 1 (65 = 'A')
- a에 적용하면 97이 65로 바뀌어 A가 됨
- 이미 대문자인 A에 같은 연산을 적용하면 그대로 A로 남음
-
소문자로 변환
- 문자를 소문자로 만들려면 32와 비트 OR를 수행함
0 1 0 0 0 0 0 1 (65 = 'A')
| 0 0 1 0 0 0 0 0 (32)
-------------------
0 1 1 0 0 0 0 1 (97 = 'a')
- A에 적용하면 65가 97로 바뀌어 a가 됨
- 이미 소문자인 a에 같은 연산을 적용하면 그대로 a로 남음
-
대소문자 반전
- 대소문자를 뒤집으려면 32와 비트 XOR를 수행함
0 1 1 0 0 0 0 1 (97 = 'a')
^ 0 0 1 0 0 0 0 0 (32)
-------------------
0 1 0 0 0 0 0 1 (65 = 'A')
0 1 0 0 0 0 0 1 (65 = 'A')
^ 0 0 1 0 0 0 0 0 (32)
-------------------
0 1 1 0 0 0 0 1 (97 = 'a')
하위 5비트로 알파벳 순번 얻기
- 알파벳 순번은 문자 코드에 31을 비트 AND해서 구할 수 있음
0 1 0 0 0 0 0 1 (65 = 'A')
& 0 0 0 1 1 1 1 1 (31)
-------------------
0 0 0 0 0 0 0 1 (1)
0 1 1 1 1 0 1 0 (122 = 'z')
& 0 0 0 1 1 1 1 1 (31)
-------------------
0 0 0 1 1 0 1 0 (26)
- 31은 이진수로 00011111이라, 앞쪽 비트를 지우고 하위 5비트만 남김
- ASCII에서 알파벳 문자의 하위 5비트는 알파벳 위치와 맞아떨어짐
- A/a는 00001로 끝나 1이 되고, B/b는 00010으로 끝나 2가 되며, Z/z는 11010으로 끝나 26이 됨
- ASCII 문자 코드에서 c & 31은 c % 32와 같음
- 32가 2의 거듭제곱이기 때문에, 31로 마스킹하면 32 단위 묶음을 제거하고 남은 부분만 보존함
'A' = 65 → 65 % 32 = 1
'B' = 66 → 66 % 32 = 2
...
'Z' = 90 → 90 % 32 = 26
'a' = 97 → 97 % 32 = 1
'b' = 98 → 98 % 32 = 2
...
'z' = 122 → 122 % 32 = 26