2017년 1월 23일 월요일

컴퓨터 부동 소수점, 고정 소수점 이해, Visual Basic Macro에서 사용하는 데이터 형식

2024-02-14-수 수정

수학에서 말하는 수의 종류와 컴퓨터에서 표현법이다.

  • 자연수 : 0 이상의 양의 정수, 예) 0, 1, 2, 3...
  • 정수 : 소수가 없는 정수, 예) –3, -2, -1, 0, 1, 2, 3
  • 소수 : 0.XXX로 1보다 작은 수, 예) 0.123, 0.01%
  • 실수 : 정수 + 소수, 예) 123.456, 3.141592
  • 고정 소수점 표현 : 예) 정수부 3자리 + 소수부 3자리 = 123.456
  • 부동 소수점 표현 : 예) 가수부 3자리 x 지수부 3자리 = 0.123456×10¹²³

숫자를 표현할 수 있는 공간(칸)이 6개라고 하자. 여기서 고정 소수점이란 소수점의 위치가 고정 되어 있음을 뜻한다. 소수점 위 3자리, 소수점 아래 3자리처럼 말이다. 부동 소수점이란 소수점 위치가 가변적이란 얘기다. 부동浮動float플로우트는 떠다님을 의미한다. 다른 말로 지수 형태 표현이라고 할 수 있다. 소수점의 위치는 지수指數가 결정하고, 수의 정밀도는 가수가 결정한다. 가수假數란 가짜 수란 의미인데 소수점 이하를 의미한다.

컴퓨터 메모리를 너무 어렵게 생각하지 말자. 우리가 초등학교 때 사용하던 원고지처럼 바둑판 격자가 그려진 공책을 상상하면 된다. 각 칸에는 글자 하나 적을 수 있다. 숫자를 적을 공간에 한계가 있는 것은 당연하다. 컴퓨터 메모리도 그러하다. 한 바이트라고 하는 것을 알파벳 문자가 들어가는 자리라고 생각하라. 

예를 들면 분해능 1000의 저울이 있다고 하자. 1g단위로 1kg까지 측정하는 저울이 있고, 1kg단위로 1톤까지 측정하는 저울이 있다. 여기서 저울 눈금에 표시되는 숫자는 가수에 해당한다. 눈금 간격이 정밀도(분해능)를 나타낸다. 그 뒤의 단위(g/kg)는 지수에 해당한다. 이건 규모(크기)를 나타낸다. 이 정도 설명해도 이해 못 하면 국정원 댓글 용역들이다.

그런데 기억 공간이란 것은 한계가 있다. 공간(칸수) 제약이 있는 숫자 표시를 할 때는 2가지 개념이 있다. 측정기나 컴퓨터 속의 수를 너무 어렵게 생각하지 말자. 중앙이 0이고 좌우가 ±30㎝인 자를 상상하자. 이 자의 최소 눈금은 1㎜이다. 그럼 이렇게 정리 할 수 있다.

  • 범위 : ±300㎜ → 크기
  • 눈금 : ±1㎜ → 정밀도/분해능

범위는 얼마나 큰 수, 작은 수를 표현할 수 있느냐이고, 눈금은 얼마나 섬세하게 나누어 표현할 수 있느냐이다. 이런 숫자 표현을 컴퓨터에선 비트 나열로 어떻게 할까? 그게 궁금하다. 2진수와 10진수를 바꾸는 개념이 필요하다. 몇 개의 숫자는 기억하자.


  • 1바이트(08비트) : 256개 정수 표현
  • 2바이트(16비트) : 6만5536개 정수 표현
  • 4바이트(32비트) : 42억9496만7296개 정수 표현
  • 8바이트(64비트) : 184경4674조4073억7095만51616개 정수 표현


Visual Basic Macro에서 사용하는 데이터 형식


컴퓨터에서 하나의 데이터 표현에 사용하는 기억 공간은 현재 8바이트(64비트)까지이다. 1바이트(8비트)에서 시작해서 2배씩 증가하는 것이 전통이다. 주어진 바이트 공간이 같아도 내용을 어떻게 해석하느냐의 차이가 있어 Data Type(자료 종류)이라 부른다.

  • 1바이트 : byte(자연수)
  • 2바이트 : integer(정수), boolean(논리)
  • 4바이트 : long(정수), single(실수)
  • 8바이트 : longlong(정수), double(실수), currency(화폐), date(시간)


대부분 컴퓨터 언어에선 전통적인 숫자 표현이다. 정수의 경우는 이해하기 쉽다. 고로 실수를 어떻게 표현하는지 분석해 볼 것이다. single, double, date는 부동 소수이고, currency가 고정 소수이다. 기타 흥미로운 자료형도 있다.

  • 14바이트 : decimal(10진수)
  • 16바이트 : variant(가변적)


decimal은 10진수를 표현한 것이다. 이건 단독 사용이 안 되고 variant와 함께 사용해서 다른 수를 10진수 형식으로 바꾼다. variant는 여러 형태의 데이터를 다 표현할 수 있도록 넓힌 공간이라 가장 많은 바이트를 차지한다. 추가된 2바이트는 자료 형식에 대한 정보이다. 고로 10진수 표현이 어떠한지 분석해 볼 것이다.

기타 object(객체), longptr(포인터) 등은 메모리 주소(위치)와 데이터 구조를 나타내는 자연수로 사람이 직접 건드릴 일이 없다. 데이터 구조란 여러 종류의 자료형을 묶어서 한 덩어리로 취급할 때 필요한 것이다. 고로 위치/크기/종류를 모두 구분해야 한다. 주소의 바이트 크기도 시스템(CPU + O/S)에 따라 자동으로 바뀌니까 신경 쓸 일 없다. 이와 유사한 자료 형식이 있다.

  • string(고정) : 문자열 길이(약 6만까지)
  • string(가변) : 10바이트 + 문자열 길이(약 20억까지)
  • variant(문자열) : 22바이트 + 문자열 길이(약 20억까지)


길이가 가변적인 자료형의 대표적이고 전통적인 것이 문자열이다. 길이가 고정된 문자열은 보통 단어 목록(사전)을 표현할 때 사용한다. 최대 한계 길이(약 6만까지 가능)를 정해서 사용한다. 단어 길이가 6만(65536자)이면 한글 250자 원고 (10행x25자) 240 페이지 분량, 500자 원고 (25행x20자) 120 페이지 노트 정도 된다. 여하튼 최대 단어 길이를 정하고 미리 공간을 확보하는 것이다. 이게 말이 단어지 이 정도면 문서 하나 정도가 들어간다.

길이가 가변적인 것은 보통 문장(문단)을 표현할 때 사용한다. 메모리는 절약 되지만 구현이 복잡하다. 문자열은 바이트의 배열이 된다. 고로 문자열 변수는 이 배열의 주소(위치)를 가리키게 되면서 문자열 길이도 표현해야 한다. 고로 4바이트(약 20억)는 길이, 나머지 4바이트는 주소(위치)를 표현하는 것 같은데 남은 2바이트는 뭔지 모르겠으나 컴퓨터가 알아서 할 일이다.

데이터를 비트로 표현하는 방법을 분석하기 위해 사용할 프로그램이다.


2진 부동 소수점 형식 분석


10진수로 된 실수를 2진수로 바꾸는 것은 정확하지 않고, 계산도 복잡하다. 고로 가수, 지수, 부호 비트를 구분해서 분석하려면 대가리를 좀 굴려야 한다. 2진수는 m×2ⁿ 형태이고 m(가수), n(지수)는 부호가 있다. n과 m의 변화를 보기 위해서 다음과 같은 수를 저장해 본 후에 분석한다.


m
n
10진양수
10진음수
1
0
1
-1
1
1
2
-2
1
2
4
-4
1
3
8
-8
1
4
16
-16
1
5
32
-32
1
6
64
-64
1
7
128
-128
1
8
256
-256
1
9
512
-512
1
-1
0.5
-0.5
1
-2
0.25
-0.25
1
-3
0.125
-0.125
1
-4
0.0625
-0.0625
1
-5
0.03125
-0.03125
1
-6
0.015625
-0.015625
1
-7
0.0078125
-0.0078125
1
-8
0.00390625
-0.00390625
1
-9
0.001953125
-0.001953125
0.1
0
0.5
-0.5
0.11
0
0.75
-0.75
0.111
0
0.875
-0.875
0.1111
0
0.9375
-0.9375
0.11111
0
0.96875
-0.96875
0.111111
0
0.984375
-0.984375
0.1111111
0
0.9921875
-0.9921875
0.11111111
0
0.99609375
-0.99609375
11
0
3 -3
111
0
7 -7
1111
 0
15 -15
11111
0
31 -31
111111
0
63 -63
1111111
0
127 -127
11111111
0
255 -255


간단한 비교 분석을 통해 다음과 같은 결론에 도달한다. 첫 비트는 부호, 그 다음은 지수, 그 다음은 1이 생략된 가수이다. 바이트의 배치 순서는 CPU에 따라 다른데 PC에서 사용하는 인텔 CPU는 하위 바이트를 먼저 기록한다. 그래서 거꾸로 배치해야 사람이 읽기 편하다. 지수는 비트 1자리만 늘어도 2배로 커지는 효과가 있다. 가수는 비트가 2배로 늘어야 2배 정밀도가 된다.


  • 32비트 실수 최소 눈금 : ±1.401298E-45 (2진수이기 때문에 이렇다)
  • 64비트 실수 최소 눈금 : ±4.94065645841247E-324 (2진수이기 때문에 이렇다)

최소 값일 때는 비트 모양이 지수 = 0, 가수 = 000...0001 꼴이다.








날짜와 시간 표현은 64비트 부동 소수점 형식을 빌려 사용하고 있다. 초→분→시→일→월→년으로 1초 시간에 해당하는 소수를 계속 누적하는 형태이다. 1일은 정수 1에 해당한다. 고로 1일을 60초 * 60분 * 24시 = 86400초로 나누면 단위 시간 1초에 해당하는 소수를 구할 수 있다. 365일은 평년, 366일은 윤년이다.


  • 최소 눈금 : 1초 =  0.0000115740740740740... (740무한 반복)
  • 최대 범위 : 1900년 1월 0일 자정(0시0분0초) ~ 약 9999년(1만년)까지






10진 고정 소수점 형식 분석


돈 계산할 때 사용하는 Currency 고정 소수점 형식은 정수와 다를 것 없다. 본질적으로 정수이다. 정수처럼 첫 비트가 부호이다. 양수=0, 음수=1이며 음수는 정수처럼 보수를 취한다. 10진수로 소수점 아래 4자리까지 표현하고 싶다면 10000에 해당하는 수를 1로 보는 방식이다. 다시 말하면 1만 배 곱하여 저장, 계산한 후에 10진수로 결과 표시할 때만 소수 4자리 앞에 살짝 소수점을 찍어 준다. 고로 비트 패턴으로는 정수와 소수의 구분이 없고 그냥 1만배가 된 정수이다.

  • 최소눈금 : ±0.0001 (10진수라서 최소 눈금을 1로 표현 가능)
  • 최대범위 : 약 ±2의 63승 ÷ 10000






10진 부동 소수점 형식 분석


Decicmal의 형식을 읽을 수는 없었으나 10진법이라는 것도 Currency처럼 최소 눈금을 정하고 정수처럼 취급하는 방법으로 보인다. 왜냐하면 최소 눈금은 10진수로 표현했을 때만 1로 끝나기 때문이다. 또한 최대 범위를 보면 약 12바이트가 가수로 사용된다. 고로 남은 2바이트가 부호와 지수가 될 것이다. 헌데 지수가 있다는 말은 부동 소수란 말이다.


  • 최소 눈금 : ±0.0000000000000000000000000001, 10진수 29자리 표시
  • 최대 범위 : 약 ±2의 96승(12바이트), 10진수 29자리 표시


이 방법은 가수는 일반 정수처럼 취급하고, 지수는 10진수로 보는 방식이다. 계산은 내부적으로 어떤 방식으로 알아서 할 것이고, 화면에 표시할 때만 소수점 위치를 살짝 결정해 찍어주는 방법이다. 이렇게 하는 이유는 계산의 정확도를 위함이다. 10진 소수를 2진 소수로 정확히 바꿀 수는 없다. 허나 정수에선 가능하다. 고로 2진수 1을 10진수 최소 눈금으로 잡은 것이다.

이 방법으로도 곱하기 나누기에선 문제가 없다. 가수는 서로 곱하고 나누고, 지수는 서로 더하고 빼면 된다. 문제는 더하기 빼기이다. 지수가 큰 쪽으로 자리수를 맞추어야 하는데 가수는 2진 정수인데 지수는 10진수를 표시하니 복잡하다. 뭐 알아서 잘 했겠지.

이제 정수로 실수를 표현하는 원리를 알았으니 직접 구현할 수도 있을 것이다. 대충 이렇게 마무리한다.






독재정부가 하는 짓은 동서고금 똑같다.
전쟁터에서 하는 짓은 동서고금 똑같다.
한 나라의 역사만 제대로 알아도 나머지 나라 역사를 안다. 외국사 = 한국사
그러니 독재자 이승만, 박정희, 김일성, 한국 전쟁에 대한 환상을 깨자.
우리가 학교에서 배운 한국사는 1920년부터 일본이 가르친 일제 식민 사학이다.
근현대사 또한 친일파 세력 때문에 제대로 교육 받았다고 할 수 없다.

2017년 1월 21일 토요일

Excel(엑셀)로 File Debugger(파일 디버거) 만들기, 유니코드 파일 분석

옛날 DOS 시절에 사용하던 디버거 프로그램이 없어서 Excel로 만들었다. CPU, O/S, 컴퓨터 언어가 진화하면서 옛날 기계어(어셈블리어)를 사용할 필요가 없어졌다. 고로 CPU 명령어 해석은 불필요하니 파일 데이터만 분석하는 기능만 만들면 된다. Excel의 편리한 인터페이스와 계산 능력을 사용할 수 있어 훨씬 좋은 디버거를 만들 수 있다.





위 화면은 파일의 일부를 바이트 단위로 읽어 여러 방법으로 해석해서 보여주는 화면이다. 옛날 디버거를 사용해 보고 필요하겠다싶은 해석을 넣었다. 일부 바이트를 수정한 후에 써넣을 수도 있다. 그러니 원본 파일을 이름을 바꿔 보전한 후에 해킹을 해야 한다.

8비트 정수를 10진수, 16진수, 2진수로 나타낸다. 16진수는 디버거에서 많이 보는 형태이나 별로 쓸모가 없다. 때론 2진수 패턴을 분석할 필요가 많다. 그리고 16비트로 묶어 정수로 볼 필요도 있다. 문자열이 섞인 경우를 보기 위해 7비트 아스키 문자, 16비트 한글 완성형 문자로 묶어 표현한다. 먼저 기록된 바이트를 상위 바이트로 보는 것은 완성형 코드이고, 하위 바이트로 보는 것은 16비트 정수일 때다.

파일에 따라 때론 32비트 정수, 유니코드 문자 등으로 해석할 필요가 있는데 원리가 같으니 직접 우측 공백에 함수를 이용해 만들어 넣으면 된다. 이런 다양한 해석은 Excel 함수를 이용해서 직접 만들어 넣으면 된다. 





위 화면은 2개 파일의 헤더부분을 비교할 때 사용하는 화면이다. 같은 종류의 파일은 헤더(머리) 부분의 패턴이 거의 같다. 고로 기준이 되는 파일과 내용에 있어 약간의 차이가 나는 비교 파일에서 그 차이 나는 부분만 찾아 표시해 줘서 파일 구조 해석에 도움을 준다.

위와 같이 화면을 만든 후에 다음 코드를 모듈에 복사해 넣어 버튼에 연결시킨다. 화면에서와 같이 정확한 행렬(가로/세로) 위치에 만들어야한다. 그림에서와 같은 Test 파일을 만들어 동작 시험을 해 본다.


Public Sub ReadFile()
    '주소, 값 영역 지우기
    Range("A5:B5").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.ClearContents
    '파일 이름, 주소, 읽을 수량 지정
    Filename = Worksheets("디버거").Cells(1, 4).Value
    ByteAddress = Worksheets("디버거").Cells(2, 4).Value
    ByteCount = Worksheets("디버거").Cells(3, 4).Value
    Dim ByteValue As Byte
    '내용 읽어서 배치, EOF보다는 LOF를 쓰는 것이 깔끔하다.
    Open Filename For Binary As 1
        For i = 0 To ByteCount - 1
            If ByteAddress + i > LOF(1) Then Exit For
            Get #1, ByteAddress + i, ByteValue
            Worksheets("디버거").Cells(5 + i, 1).Value = ByteAddress + i
            Worksheets("디버거").Cells(5 + i, 2).Value = ByteValue
        Next i
    Close 1
    '다음 주소 자동 계산
    Worksheets("디버거").Cells(2, 4).Value = ByteAddress + ByteCount
End Sub


Public Sub WriteFile()
    Filename = Worksheets("디버거").Cells(1, 4).Value
    Dim ByteValue As Byte
    Open Filename For Binary As 1
        i = 0
        ByteAddress = Worksheets("디버거").Cells(5 + i, 1).Value
        Do While ByteAddress <> ""
            ByteValue = Worksheets("디버거").Cells(5 + i, 2).Value
            Put #1, ByteAddress, ByteValue
            i = i + 1
            ByteAddress = Worksheets("디버거").Cells(5 + i, 1).Value
        Loop
    Close 1
End Sub


Public Sub CompareFile()
    '주소, 값 영역 지우기
    Range("A3:B3").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.ClearContents
    Range("I3:J3").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.ClearContents
    '파일 이름 지정
    FileName1 = Worksheets("비교").Cells(1, 4).Value
    FileName2 = Worksheets("비교").Cells(1, 12).Value
    '파일 길이 비교
    Dim ByteValue1 As Byte
    Dim ByteValue2 As Byte
    Open FileName1 For Binary As 1
    Open FileName2 For Binary As 2
    filelength1 = LOF(1)
    filelength2 = LOF(2)
    MaxLength = filelength1
    minlength = filelength2
    If filelength1 < filelength2 Then
        MaxLength = filelength2
        minlength = filelength1
    End If
    '헤더 부분 비교 차이 나는 부분만 표시
    r = 3
    For i = 1 To minlength
        Get #1, i, ByteValue1
        Get #2, i, ByteValue2
        If ByteValue1 <> ByteValue2 Then
            Worksheets("비교").Cells(r, 1).Value = i
            Worksheets("비교").Cells(r, 2).Value = ByteValue1
            Worksheets("비교").Cells(r, 9).Value = i
            Worksheets("비교").Cells(r, 10).Value = ByteValue2
            r = r + 1
        End If
    Next i
    For i = minlength + 1 To MaxLength
        If filelength1 = MaxLength Then
            Get #1, i, ByteValue1
            Worksheets("비교").Cells(r, 1).Value = i
            Worksheets("비교").Cells(r, 2).Value = ByteValue1
        End If
        If filelength2 = MaxLength Then
            Get #2, i, ByteValue2
            Worksheets("비교").Cells(r, 9).Value = i
            Worksheets("비교").Cells(r, 10).Value = ByteValue2
        End If
        r = r + 1
    Next i
    Close
End Sub


이걸 왜 만들었냐고? 옛날 게임 데이터 파일 해킹하려고. 요즘 것은 암호화 되어 있다.

자 이제 어떻게 사용하는지 보도록 하자. 사용법을 알면 감이 잡힐 것이다. 노트패드에서 숫자, 알파벳, 한글의 시작과 끝 문자를 입력해 넣고 4가지 표준으로 저장한다.


  1. ANSI(기존표준) = 영문 아스키 + 한글 완성형(한글 부족) + MS CP949(한글 보충)
  2. 유니코드(UTF-8) = 통신 목적으로 사용하며 기존 영문 아스키와 호환을 유지한다.
  3. 유니코드(UTF-16 little Endian) = 16비트로 세계 문자 표현. 하위 바이트 먼저 기록.
  4. 유니코드(UTF-16 Big Endian) = 16비트로 세계 문자 표현. 상위 바이트 먼저 기록.


※ Endian(엔디안)은 여러 바이트가 하나의 의미를 나타낼 때 바이트 저장 순서를 말한다. 예를 들어 123(백이십삼)을 저장(기록)할 때 기계에 따라 1, 2, 3 순서와 3, 2, 1 순서로 저장해서 구분이 필요한 것이다. IBM PC의 Intel CPU는 3, 2, 1 순서로 기록한다. 옛날 Mac PC 등 다른 컴퓨터 CPU는 1, 2, 3 순서로 기록할 수도 있다.





기존 파일 형식에선 문자 파일의 경우 아무런 예고도 없이 내용이 나온다. 왜냐하면 파일 확장자에 *.txt로 문자 파일임을 나타내기 때문이다. 계산해 보면 0~9, a~z, A~Z까지 숫자가 순서대로 할당되어 있다. 한글 완성형의 경우는 2바이트를 묶어 해석해야 한다. 이 때 상위/하위 바이트를 앞에 것으로 하느냐 뒤의 것으로 하느냐 정해야 하는데 문자의 경우 먼저 나온 것을 보고 뒤의 것을 해석하기 때문에 앞의 것을 상위 바이트로 본다. 16비트 정수 해석은 여기선 필요 없으니 무시한다.

※ 완성형의 경우 시작과 끝 글자의 순서가 뒤죽박죽인데 띨띨하게 완성형 만들 때 모든 한글을 반영하지 않았다. 약 2천 개만 등록했던 것이다. 그래서 MS사(社)에서 불쌍하다며 CP949란 보충 코드를 만들어 주다보니 이렇게 되었다.

유니코드 중에 UTF-8은 기존의 ANSI 문서 파일이 아님을 나타내기 위해서 첫 3바이트가 헤더 형태로 나온다. 그 다음은 아스키와 호환성을 유지하니 같다. 한글 코드가 3바이트로 할당 되어 있는데 이건 가변길이 코드이다. 1번 바이트의 특징을 보고 2번 바이트를 이어 해석하고, 2번째 바이트를 보고 3번 바이트를 이어 해석하는 방식이다. 그러다 보니 한글이 3바이트나 차지하게 되었다. 이건 유니코드를 공부해야 해석이 가능하다. 비트 패턴을 보고 해석해야 한다.

유니코드 중에 UTF-16 Little Endian 순서가 PC에서 표준인 것 같다. PC에선 16비트 정수의 경우 하위 바이트를 먼저 저장한다. 고로 문자 코드는 16비트 정수 해석과 정확히 일치한다. 기존 ANSI 파일이 아니며 UTF-16 Little Endian이란 헤더가 나온다. UTF-16 Big Endian과 정확히 반대 순서이다. 아스키(ASCII) 코드는 8비트에서 상위 바이트에 0을 더해 16비트로 그대로 확장했고, 한글의 경우 16비트 정수 해석 값이 그대로 문자 코드가 된다.

여기서 UTF-16 Big Endian과 UTF-8 가변 길이 코드를 비교해 보자. Big Endian은 우리가 숫자를 나열하는 방식과 같다. 좌측에 먼저 적는 숫자가 높은 자릿수이다. 낮은 자릿수는 가장 늦게 우측에 적는다. 사람이 기록하는 순서와 컴퓨터가 기록하는 순서가 같다. 이 방식이 인간에겐 더 자연스러운 순서이다.

가 = 1010 1100 - 0000 0000 = 1110 1010 - 1011 0000 - 1000 0000
힣 = 1101 0111 - 1010 0011 = 1110 1101 - 1001 1110 - 1010 0011

이제 알겠는가? UTF-8은 비트의 앞을 보고 뒤를 이어 해석하는 방식이다. 비트의 나머지 부분을 묶어 연결해서 UTF-16으로 만들어서 문자처리를 한다. 왜 이 짓을 하느냐? 아스키 코드와 호환성을 위해서다. 아스키 코드엔 옛날 구식 기계 동작을 제어하는 코드가 포함 되어 있어 그 코드를 피하기 위함이다. 일단 UTF-16으로 바꾸면 아주 쉽게 간단한 계산으로 한글의 초성, 중성, 종성을 분리해 낼 수 있다. 완성형은 이게 불가능하다.

첫 바이트 1110은 총 3바이트란 의미다. 1이 3번 나온다. 0은 그냥 구분용이다. 같은 방식으로 110일 경우는 총 2바이트, 11110일 경우는 총 4바이트란 의미다. 뒤에 이어지는 바이트 모두 10으로 시작한다. 만약 첫 비트가 0이면 그건 아스키 코드와 같다는 뜻이다.

대충 사용법은 알겠지? 16비트 정수 해석 순서를 바꾸려면 빈 셀에 계산식만 추가로 더 입력해 넣으면 된다.








인간처럼 똥 많이 싸고 쓰레기 많이 버리는 동물도 없을 거다.
불필요하게 많이 먹고, 불필요하게 많이 생산한다.
살기 위해 돈 벌어야 하고, 돈 벌려고 쓰레기를 만들어야 한다.
미래엔 진짜 1명만 일하고 9명이 백수인 세상이 올 것이다.
로봇(기계+컴퓨터)에 의한 복지국가 외엔 답이 없을 것이다.

2017년 1월 20일 금요일

ASCII(아스키) 코드 이해하기

미국정보교환표준부호(American Standard Code for Information Interchange; ASCII) : 1967년 표준 제정, 1986년 마지막 개정

이 코드를 이해하려면 먼저 타자기 시대를 이해해야 한다. 년도를 보면 타자기를 사용하던 시절에 제정하여, 컴퓨터 화면 출력 시절에 마지막 개정을 한다. 타자기인데 사람이 치는 것이 아니라 기계가 통신을 해서 자동으로 치는 타자기이다. 그래서 제어 명령(통신에 필요한 명령 + 타자기를 움직이는 명령)이 함께 들어 있다. 컴퓨터와 프린터도 이 아스키 코드로 통신할 수 있다. 프린터는 자동 타자기에 해당한다.


이진법
십육진법
십진법
약자
설명이 아닌 이름
엉터리 설명에 대한 추측
000 0000
00
0
NUL
Null Character
공백 문자(문자가 아니라 그냥 없음 표시)
000 0001
01
1
SOH
Start of Header
헤더 시작
000 0010
02
2
STX
Start of Text
본문 시작 & 헤더 종료
000 0011
03
3
ETX
End of Text
본문 종료
000 0100
04
4
EOT
End of Transmission
전송 종료 & 통신 초기화
000 0101
05
5
ENQ
Enquiry
응답하라!
000 0110
06
6
ACK
Acknowledgment
긍정응답 = OK/Yes/그렇다!
000 0111
07
7
BEL
Bell
경고음(삐~)
000 1000
08
8
BS
Backspace
백스페이스 = 커서 좌측 이동
000 1001
09
9
HT
Horizontal Tab
수평 탭 = 커서 우측 몇 칸 이동
000 1010
0A
10
LF
Line feed
개행 = 종이 한 줄 정도 올리기
000 1011
0B
11
VT
Vertical Tab
수직 탭 = 커서 아래 몇 칸 이동
000 1100
0C
12
FF
Form feed
다음 페이지 = 종이 넘기기
000 1101
0D
13
CR
Carriage return
복귀 = 커서 좌측 끝으로 이동
000 1110
0E
14
SO
Shift Out
확장문자(외국문자/그림문자) 시작
000 1111
0F
15
SI
Shift In
확장문자(외국문자/그림문자) 종료
001 0000
10
16
DLE
Data Link Escape
전송 제어 확장(탈출? 다른 방식으로 통신?)
001 0001
11
17
DC1
Device Control 1
장치 제어 1 (다른 장치가 있다면)
001 0010
12
18
DC2
Device Control 2
장치 제어 2
001 0011
13
19
DC3
Device Control 3
장치 제어 3
001 0100
14
20
DC4
Device Control 4
장치 제어 4
001 0101
15
21
NAK
Negative Acknowledgement
부정응답 = NG/No/아니다!
001 0110
16
22
SYN
Synchronous idle
동기 = 상대와 대화하기 위해 기다림?
001 0111
17
23
ETB
End of Transmission Block
전송블록 종료
001 1000
18
24
CAN
Cancel
무시 = 방금 전송한 것 무시해라?
001 1001
19
25
EM
End of Medium
매체 종료(중간 종료?)
001 1010
1A
26
SUB
Substitute
치환 = 잘 못 전송한 것 대체?
001 1011
1B
27
ESC
Escape
제어기능 추가(탈출? 다른 제어 명령 사용?)
001 1100
1C
28
FS
File Separator
파일경계 할당 = 파일 구분자
001 1101
1D
29
GS
Group Separator
레코드 그룹 경계 할당 = 그룹 구분자
001 1110
1E
30
RS
Record Separator
레코드 경계 할당 = 레코드 구분자
001 1111
1F
31
US
Unit Separator
장치 경계 할당(단위 구분자?)
이 구간은 화면에 표시 가능한 문자
알파벳 + 숫자 + 기호
111 1111
7F
127
DEL
Delete
삭제 = 잘 못 전송한 것 삭제?


위에서 보통 Null이라고 하면 정말 아무 것도 없는 것을 말한다. 즉, 숫자 0도 아니고 문자 공백도 아니라 정말 무(無)이다. 

1~6은 통신에 관한 것이다. 통신 시작한다. 끝낸다. 응답하라. 그런 내용이다.

7~15은 타자기를 제어하는 명령이다. 소리를 내거나. 문자를 두드리는 타자기 머리(케리지, 컴퓨터에선 커서)와 종이 넘기는 바퀴를 제어하는 것이다. 머리를 좌우로 한 칸 움직이거나 종이를 한 줄, 한 페이지 넘기는 것 등이다. 고로 컴퓨터에서 Enter는 LF+CR = CR+LF 조합이다.

16~20은 뭔가 다른 기계 장치가 연결 되어 있으면 그걸 제어하려는 명령이다. Escape는 탈출을 의미한다. 보통 무조건 빠져나가는 것을 의미한다. 헌데 이걸 중간에 다른 명령 삽입이라고 해석할 수도 있다. 보통 이런 코드 바로 뒤에 오는 코드는 다른 의미로 해석한다.

21~31, 127은 나중에 추가한 것 같다. 왜냐하면 보통 짝을 지어 나타나는 것들은 함께 제정한 것인데 나중에 추가한 것들은 땜질을 한 것이라 위치가 추가한 순서가 된다. 뭔가 통신 장애에 대한 대책과 메모리 기능이 있는 장치(프린터)에서만 통하는 명령이다. 이미 종이에 찍은 것을 취소하거나 지울 수는 없기 때문이다. 프린터는 자체 메모리가 있어 내용을 적당히 받은 후에 출력을 한다.


2진법
십육진법
십진법
모양
010 0000
20
32
공백
010 0001
21
33
!
010 0010
22
34
"
010 0011
23
35
#
010 0100
24
36
$
010 0101
25
37
%
010 0110
26
38
&
010 0111
27
39
'
010 1000
28
40
(
010 1001
29
41
)
010 1010
2A
42
*
010 1011
2B
43
+
010 1100
2C
44
,
010 1101
2D
45
-
010 1110
2E
46
.
010 1111
2F
47
/
011 0000
30
48
0
011 0001
31
49
1
011 0010
32
50
2
011 0011
33
51
3
011 0100
34
52
4
011 0101
35
53
5
011 0110
36
54
6
011 0111
37
55
7
011 1000
38
56
8
011 1001
39
57
9
011 1010
3A
58
:
011 1011
3B
59
;
011 1100
3C
60
<
011 1101
3D
61
=
011 1110
3E
62
>
011 1111
3F
63
?
100 0000
40
64
@
100 0001
41
65
A
100 0010
42
66
B
100 0011
43
67
C
100 0100
44
68
D
100 0101
45
69
E
100 0110
46
70
F
100 0111
47
71
G
100 1000
48
72
H
100 1001
49
73
I
100 1010
4A
74
J
100 1011
4B
75
K
100 1100
4C
76
L
100 1101
4D
77
M
100 1110
4E
78
N
100 1111
4F
79
O
101 0000
50
80
P
101 0001
51
81
Q
101 0010
52
82
R
101 0011
53
83
S
101 0100
54
84
T
101 0101
55
85
U
101 0110
56
86
V
101 0111
57
87
W
101 1000
58
88
X
101 1001
59
89
Y
101 1010
5A
90
Z
101 1011
5B
91
[
101 1100
5C
92
\
101 1101
5D
93
]
101 1110
5E
94
^
101 1111
5F
95
_
110 0000
60
96
`
110 0001
61
97
a
110 0010
62
98
b
110 0011
63
99
c
110 0100
64
100
d
110 0101
65
101
e
110 0110
66
102
f
110 0111
67
103
g
110 1000
68
104
h
110 1001
69
105
i
110 1010
6A
106
j
110 1011
6B
107
k
110 1100
6C
108
l
110 1101
6D
109
m
110 1110
6E
110
n
110 1111
6F
111
o
111 0000
70
112
p
111 0001
71
113
q
111 0010
72
114
r
111 0011
73
115
s
111 0100
74
116
t
111 0101
75
117
u
111 0110
76
118
v
111 0111
77
119
w
111 1000
78
120
x
111 1001
79
121
y
111 1010
7A
122
z
111 1011
7B
123
{
111 1100
7C
124
|
111 1101
7D
125
}
111 1110
7E
126
~


위의 코드는 종이에(모니터 화면에, 프린터에) 출력할 수 있는 문자이다. 로마 알파벳이 지금의 영어 알파벳의 원조인데 미국에서 만든 표준이라 다른 유럽 언어는 표현할 수 없다. 컴퓨터는 미국에서 먼저 만들었으니 할 수 없다. 그래서 유럽 (8비트로 확장) → 일본(16비트로 확장) → 한국(일본 모방) 등 자기 문자를 표현하려는 노력이 있었다.

아스키와 호환성을 유지하려고 제어 문자를 피하다 보니 코드가 꼬이고 지저분해졌다. 그래서 새로 깔끔하게 세계 문자코드를 만들자는 것이 유니코드인데 인터넷 통신에선 아스키와의 호환성 유지를 하려고 다시 지저분한 버전(UTF-8)을 만들어 사용하고 있다. 컴퓨터 내부에서 처리만 하려면 깔끔한 버전(UTF-16)을 사용하는 게 좋다.




한국은 법은 잘 만들었는데 사람이 지키지 않는다고 한다. 내 생각엔 개소리다.
기계는 잘 못 만들면 제대로 동작하지 않는다. 법도 마찬가지다.
대체로 법을 만드는 사람들은 두루뭉술하고 애매모호하게 만든다. 개구멍이 있다.
그래서 법을 코에 걸면 코걸이 귀에 걸면 귀걸이라고 한다.
정신 나간 대통령 탄핵도 못 하는 나라다. 판사 필요 없으니 배심원제 하자.