데이터
이진수와 2의 보수
컴퓨터는 어떻게 0과 1 즉 이진수로 양수, 음수, 소수, 문자를 표현할 수 있을까?
양수는 이진수로, 음수는 2의 보수로 소수는 부동소수점으로 문자는 문자집합과 인코딩으로 이해한다.
이진법(이진수)
- 이진법은 0과 1로 모든 수를 표기하는 방법이다.
- 이진수는 0과 1만으로 표현된 수이다.
- 1을 넘어가는 시점에 자리올림을 한다.
- 단점: 숫자가 너무 길어진다!
십육진법(십육진수)
- 십육진법: 1~9과 A~F로 모든 수를 표기하는 방법
- A==10, B==11, C==12, D==13, E==14, F==15
- 15(F)을 넘어가는 시점에 자리올림!
- 십진수말고 십육진수를 사용하는이유는 이진수와 십육진수의 변환이 편한다.
2의 보수법
- 0과 1만으로 음수를 표현하는 방법 중 하나
- 어떤 수 n을 그보다 큰 2^n에서 뺀 값
- 11의 2의 보수는 100에서 뺀 01
- 모든 0과 1을 뒤집은 뒤 1을 더한 값
- 0과 1만으로 음수를 표현하면 양수와 음수를 구분하기 어렵지 않을까?
- CPU 내부의 레지스터 중 하나인 플래그(flag)가 있다.
- 플래그: CPU가 명령어를 실행하는 과정에서 참고할 정보의 모음
- 음수 플래그가 세팅 되어 있을 경우: 음수로 인식
- 음수 플래그가 세팅 되어 있지 않을 경우: 양수로 인식
부동 소수점
floating point, 소수점이 어디 있는 지 움직일 수 있다는 뜻
부동 소수점 표현은 잘 이해하지 못하면 개발에서 당황스러운 상황이 있다.
아래 파이썬 코드의 결과는 무엇일까?
a = 0.1
b = 0.2
c = 0.3
if a + b == c:
print("EQUAL")
else:
print("NOT EQUAL")
위의 코드 결과는 NOT EQUAL이 나온다.
그 이유는 컴퓨터 내의 소수점 표현 방식의 한계 때문이다.
즉, **부동 소수점(floating point)**의 한계 때문!
부동 소수점에 대해 알려면 지수 와 가수에 대해 알아야 한다.
아래 이미지에서 파란글씨는 가수(significand)이고 빨간글씨는 지수(exponent)이다.
- 123.123
- 123.123 결과가 나온다.
컴퓨터 내부의 소수 표현 방식은 부동 소수점 표현 방식이고
이진수를 m * 2^n꼴로 나타내고, 가수 부분은 1.XXX 꼴을 띄고 있다. (XXX 부분 즉, 소수 부분만 저장된다.)
지수 부분이 저장될때면 bias(바이어스)값이 더해져 저장됨.
바이어스: 2^(k-1)-1, k는 지수의 비트 수
그래서 결과가 왜 NOT EQUAL이 출력 되었는가
십진수 소수를 이진수로 표현할 때 십진수 소수와 이진수 소수 표현이 딱 맞아 떨이지지 않을 수 있다.
- 예) 1/3이라는 분수 m * 3^n 꼴로 표현하면 딱 떨어진다.
- 예) 1/3이라는 분수 m * 10^n 꼴로 표현하면 무한히 많은 가수가 필요하다.
- 0.3333333333333 무한히 많은 가수가 필요
- 이진수를 m * 2^n로 나타내니 우리가 사용하는 십진수와 딱 떨어지지 않는 것 이다.
컴퓨터 내부에서는 가수를 저장할 수 있는 공간이 한정적이다.
그렇기 떄문에 무한히 가수가 필요한 부분은 버릴 수 밖에 없어 오차가 발생한다
그래서!! 답이 다르게 나오는 것이다!!!
문자 인코딩과 디코딩
문자 인코딩: 문자열을 컴퓨터가 이해할 수 있기에 변환하는 것 0과 1로 변환
문자 디코딩: 0과1로 이루어진 수를 사람이 이해할 수 있게 디코딩 하는 것.
0과 1로 문자 표현하기
- 문자 집합(character set): 표현 가능한 문자들의 집합
- 문자 인코딩: 문자를 0 과 1로 이루어진 문자 코드로 변환
- 문자 디코딩: 0과 1로 이루어진 문자 코드를 문자로 변환
만약 내가 친구에게 글을 적어 문자로 전송을 한다면 인코딩을 하여 컴퓨터에 보내주고 컴퓨터가 다시 디코딩하여 친구에게 보내는 것이다.
- 개발을 하다가 문자 깨진다면?
- 컴퓨터가 이해할 수 없는 인코딩 방식 혹은 지원되지 않는 문자열 사용
- 인코딩 방식 확인이 대부분의 해결 방법이다.
- 오늘날의 인코딩 방식은 대부분 영어를 지원한다.
아스키 코드(ASCII)
초창기 문자 집합, 알파벳 + 아라비아 숫자 + 일부 특수 문자 + 제어 문자
- 오늘날의 대부분 인코딩 방식은 아스키코드와 호환이 된다.
- 0~127까지 알파벳, 아라비아 숫자, 일부 특수문자, 제어문자
- 아스키 코드는 기본적으로 8bit인데 실질적으로 사용하는 것은 7bit이다.
- 대응이 곧 인코딩하는 것이다. 65는 A, 97는 a,
#include <stdio.h>
int main() {
printf("%d \\n", 'a'); // a를 숫자로 출력
printf("%c \\n", 97); // 97를 문자로 출력
return 0;
}
// 결과
// 97
// a
유니코드 문자 집합
아스키 코드를 보면 문제가 있다, 한글 혹은 독일어등 다양한 언어를 표현할 수 없다.
그러면 영어를 제외한 언어를 인코딩하려면 어떻게 해야할까?
각 나라마다 언어를 인코딩 방식을 만들면 인코딩 방식이 너무 많아진다.
그렇다면 통일된 문자 집합과 인코딩 방식을 사용하자 → 유니코드 문자 집합과 유니코드 인코딩 방식
- 대부분의 언어(범용성이 높음)
- 특수문자
- 이모티콘
- 화살표 등
https://home.unicode.org 를 보면 유니코드 문자 집합을 확인 할 수 있다.
4자리 16진수 U+270C는 유니코드 포인트이다.
유니코드 포인트: 유니코드 문자에 부여된 고유한 수
그러면 아스키코드처럼 AE00을 대응하는 것 일까?
그렇지 않다. 코드포인트를 인코딩하는 방식에 따라 대표적으로 utf-8, utf-16, utf-32등으로 나눠진다.
즉, 유니코드 문자 집합을 인코딩하는 다양한 방법들이 있음
그러면 한 번 코드로 실행해서 확인해보자.
**import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("인코딩할 값을 입력하세요: ");
String inputValue = sc.nextLine();
// 유니코드 코드 포인트 출력
System.out.println("유니코드 코드 포인트:");
for (char ch : inputValue.toCharArray()) {
int codePoint = (int) ch;
System.out.printf("문자 '%c': U+%04X%n", ch, codePoint);
}
// UTF-8 인코딩
byte[] utf8Encoded = inputValue.getBytes(StandardCharsets.UTF_8);
System.out.print("UTF-8 인코딩 결과: ");
for (byte b : utf8Encoded) {
System.out.printf("%02X ", b);
}
System.out.println();
// UTF-16 인코딩
byte[] utf16Encoded = inputValue.getBytes(StandardCharsets.UTF_16);
System.out.print("UTF-16 인코딩 결과: ");
for (byte b : utf16Encoded) {
System.out.printf("%02X ", b);
}
System.out.println();
// UTF-32 인코딩
Charset utf32Charset = Charset.forName("UTF-32");
byte[] utf32Encoded = inputValue.getBytes(utf32Charset);
System.out.print("UTF-32 인코딩 결과: ");
for (byte b : utf32Encoded) {
System.out.printf("%02X ", b);
}
System.out.println();
sc.close(); // Scanner 닫기
}
}**
위의 결과를 보면 인코딩 결과가 모두 다른 것을 확인할 수 있다.
실제 유니코드를 볼 수 있는 사이트를 확인해보면 맞는 것을 볼 수 있다.
유니코드 문자에는 코드포인트가 부여되어 있다.
UTF-8,16,32 인코딩하는 방식에 따라 결과가 달라질 수 있다.
결론
이렇게 컴퓨터와 사람이 어떻게 문자를 서로 이해할 수 있고 전달을 할 수 있는 지 확인해봤다.
프로젝트를 진행하면 대부분 인코딩과 디코딩 작업을 진행해야할 때가 많다.
대표적으로 Json 데이터를 받았을 때 디코딩하는방법도 있고 이런 개념을 확실히 알고 인코딩과 디코딩을 진행하면 훨씬 수월하게 작업이 가능할것이다.
'Computer Science > Computer Architecture' 카테고리의 다른 글
[Computer Science] [컴퓨터구조] CPU(2) (0) | 2024.12.16 |
---|---|
[Computer Science] [컴퓨터구조] CPU (0) | 2024.12.14 |
[Computer Science] [컴퓨터구조] 명령어 (4) | 2024.12.12 |