창조유저그룹-커즈닷컴
Window close
ID :     PASS :   
   
  처음으로
  창조
  창조 소개
창조 다운로드
CUGz.com 소개
온라인 도움말
  커뮤니티
  가입인사
자유게시판
Q/A게시판
TIP/TECH
열린강좌
자주하는질문
아이디어게시판
  자료실
  소스자료실
프로그램자료실
기타자료실
명예의 전당
이미지 자료실
  지원/기타
  표준용어재정
구글 웹서치  
관리자 전용


LIST ALL
Posted by 지상현2012-01-03 21:05:17, Hit : 7481
컴퓨터에서 소수점을 표기하는 방식에 대해
Homepage : http://ssidang.x-y.net
Post URL : http://cugz.sjworks.net/bbs/zboard.php?id=open_lec&no=198
 창조 뿐 아니라 다른 프로그래밍 언어에서 사용하는 소수점 타입은 대부분 IEEE 754 라는 포맷을 사용해서 표현합니다.
 창조에서는 실수, C나 델파이, 자바에서는 double, VB에서는 Double 등으로 사용합니다.
 다른 언어 경험이 있어서 등 여러 이유로, 부동소수점에 대해 배우신 분은 이 글을 읽을 필요가 없습니다.

 Double이란 이름의 유래는 아마도 double-precision에서 나온게 아닐까 합니다.
 IEEE 754에는 최소 32비트로 소수점을 표현할 수 있도록 정하고 있는데, 32비트가 기본 단위라면 64비트는 32비트의 두 배(double)니까 double-precision이라 합니다.

 참고로 32비트 소수점은 다른 언어에서 부르는 이름이 조금 다릅니다. (창조에는 없습니다.)
  • C나 자바에서는 float이라고 합니다. (부동소수점floating-point 이니까)
  • 델파이에서는 real이라고 합니다. (실수real number를 표현하는 기본 타입이니까)
  • VB에서는 Single이라고 합니다. (기본 단위 하나single 짜리니까)

 어쨌든, 컴퓨터가 소수점을 표현할 수 있는 방법은 여러 가지가 있지만, 그 중 대표적인 것을 살펴보겠습니다.


고정소수점 방식 (fixed-point)

 일상생활에서 소수점을 어떻게 쓰나 생각해봅시다. 대부분 소수점 이하 두 자리 정도를 사용하는게 보통입니다.
 키를 잴 때도, 흔히 170cm 라고 표현하며 좀 더 정확하게 하더라도 170.5cm 정도로 잽니다. 몸무게도 흔히 83kg 라고 표현하며 보다 정확하게 표현하더라도 83.4kg 정도로 잽니다.
 (※주: 임의로 선택한 숫자입니다 - 전 170cm에 83kg이 아닙니다 -_-)

 보통, 사람은 하나, 둘 하고 세기 때문에 단위를 자연수에 맞추고, 소수점은 부가적으로 따라오는 경우가 대부분입니다. 그럼 이렇게 생각해볼 수 있습니다.

 "기본 단위를 m에서 mm로 바꾼다면?"

 미터를 사용하던 기본 단위를 밀리미터로 바꾸면 이렇게 됩니다.
  • 170.5cm -> 1705mm
  • 0.3m -> 300mm
  • 2.591m -> 2591mm
미터나 센티미터에서 나오던 소수점이 모두 사라졌습니다.
 마찬가지로, 고정소수점의 기본 아이디어는 기본 단위를 더 작은 것으로 쓰는 것입니다.

 예를 들어 (창조에는 없는) Currency 같은 타입을 지원하는 언어에서는, 기본 단위를 1이 아닌 1/1000을 사용합니다.
 그래서 그 타입으로 표현할 수 있는 가장 작은 값은 '0.001' 이며, '1'이라는 값을 표현하려면 0.001 을 1,000개 모아서, '1.000' 으로 표현합니다. (실제 값은 1,000 입니다.)

 그보다 정밀한 수 (0.00001 같은)를 표현할 수 없고, 단순히 소수점을 왼쪽으로 3칸 옮긴 것과 똑같으며, 소수점이 그 자리에 고정되기 때문에 고정소수점이라 합니다.



부동소수점 방식 (floating-point)

 하지만 과학 계산이나 수학적인 계산을 할 때를 생각해봅시다.
 숫자를 잘 보면,
  • ← 12345...
 숫자가 커질수록 왼쪽으로 숫자가 더 많이 생깁니다.
 그런데,
  • ← 12345.6789 →
 숫자가 작아질수록 오른쪽으로 숫자가 더 많이 생깁니다.
 즉, 소수점을 표현하면 숫자가 왼쪽으로도, 오른쪽으로 계속 늘어난다는 것입니다.

 기존에 사용하던 방법은 숫자가 왼쪽으로 늘어나는 경우-커지는 경우만 처리할 수 있는데, 소수점은 오른쪽으로 늘어나는 경우도 있습니다.
 어떻게 해야 소수점을 제대로 표시할 수 있을까요?

 사람들은 오차를 감수하는 방법을 고안해냈습니다.
 원주율은 무리수이기 때문에 소수점으로 표현하면 끝없이 숫자를 나열해야 합니다. 하지만 대부분은 3.14 정도로 간단히 사용하고, 더 복잡해도 3.1415 정도를 사용합니다.

 마찬가지로 계산할 때는 대부분 소수점 두 자리 정도로 반올림합니다. 3.1415 대신 3.14를 쓰는 게 의미가 있는 이유는, 생략된 0.0015가 생략하지 않은 3.14보다 오차에 끼치는 영향이 훨씬 적기 때문입니다.

 다시 말해, 대부분의 경우 숫자가 ← 방향으로 커지는 것이 → 방향으로 줄어드는 것보다 중요합니다.
 부동소수점 방식은 이에 착안하여, 숫자를 → 방향으로만 늘려나갑니다. 그 대신, 이번에는 소수점이 들어가야 할 위치도 기억해서 소수점의 위치를 바꿔줍니다.

 십진수로 예를 들면,
  • 3.14
  • 0.314
  • 31.4
 위 숫자들은 서로 다른 숫자들이지만, 계급장(?)을 떼고 보면 모두
  • ...314...
 로 숫자 열이 같습니다.

 부동소수점 방식에서는 먼저 저런 숫자를 표현하려고 정규화라는 것을 합니다. 숫자를 무조건 1의 자리에 맞추는 것이죠.
 여기서 ...314... 라는 숫자의 정규화된 꼴은 3.14입니다. 12345의 정규화된 꼴은 1.2345가 되겠지요.

 물론 3.14로는 31.4를 표현할 수 없습니다. 대신 소수점의 위치를 옮겨줍니다. 3.14를 3.14로 만들려면 소수점을 오른쪽으로 하나 옮겨주면 됩니다.
 수학적으로 표현한다면, 10을 곱해주면 됩니다. 소수점을 왼쪽으로 옮겨주려면 10을 나눠도 되고, 1/10을 곱해도 되겠지요.
 이런 식으로 해서 위에 적은 숫자를 부동소수점 방식으로 바꾸면 이렇게 됩니다.
  • 3.14 -> 3.14 x 1
  • 0.314 -> 3.14 x 0.1
  • 31.4 -> 3.14 x 10
 모두 똑같이 3.14란 숫자열에 자릿수를 표시하는 숫자만 곱하는 것입니다.
여기에, 제곱 표기를 이용하면 더욱 괜찮게 표시할 수 있습니다.
  • 3.14 -> 3.14 x 10^0
  • 0.314 -> 3.14 x 10^(-1)
  • 31.4 -> 3.14 x 10^1
 10^0 = 1 이고, 10^(-1) = 0.1 이고, 10^1 = 10 이니까 똑같습니다.

 이 방법을 사용하면, 31400은 3.14 x 10^4 로, 0.00314는 3.14 x 10^(-3) 으로 표현할 수 있습니다.

 사실 이 방법은 컴퓨터에서만 쓰는 방식이 아닙니다. 지수표기법이라 하는 이 방법은, 과학에서 흔히 쓰는 방법입니다.
 천문학에서 쓰는 숫자들은 말 그대로 '천문학적 스케일'이기 때문에, 숫자를 순진하게(?) 적으면 이래 저래 고생입니다. 예를 들어 지구와 태양 사이의 거리는 약 150,000,000km 라고 하는데, 매번 이렇게 적을 수 없습니다. 그래서 간단하게 1.5 x 10^8 km 라고 적습니다.
 반면에 전자의 전하량은 약 1.6 x 10^(-19) C 입니다. 이걸 풀어 쓴다면 0을 엄청 써야겠지요.

 지수표기법을 간단하게 적으면,
  • 1.5 x 10^8 -> 1.5e8 (또는 1.5e+8)
  • 1.6 x 10^(-19) -> 1.6e-19
 가 됩니다. 어디서 많이 본 표기법일 겁니다.

 어쨌든, 이렇게 적으면 1.5 x 10^8 이란 숫자를 표현할 때, 15 란 숫자열과 8이란 자릿수만 기억하고 있으면 된다는 것이 바로 부동소수점 방식입니다. 하나 더, 양수인지 음수인지 부호도 기억하고 있습니다.

 부동소수점은 크게 부호 / 지수부 / 가수부로 숫자를 기억하고, 부호는 말 그대로 음수인지 양수인지, 지수부는 자릿수, 가수부는 어떤 숫자열이 들어가는지를 기억합니다.

 창조에서 사용하는 실수(64비트 부동소수점)는, 가수부를 십진수로 15자리 정도 기억할 수 있습니다. 애초에 단위가 이진수이기 때문에, 이를 사람에게 익숙한 십진수로 풀면 15자리 정도 된다는 뜻입니다.
 또한 지수는 십진수로 308 까지 쓸 수 있습니다. 3.14e+300 은 OK지만, 3.14e+400 은 OK가 아닙니다. 실수로 표현할 수 없습니다. (실제로는 +INF 라는 값으로 표현합니다.)



부동소수점 실제 표현

 지금까지는 익숙한 십진법으로 표기했지만, 컴퓨터는 이진법을 쓰기 때문에, 부동소수점도 사실 이진법을 사용해서 표현합니다.
 즉 1.5 x 10^8 처럼 표현하지 않고, 1101101b x 2^(1101b) 같은 식으로 표현됩니다.
 십진수를 이진수 표현으로 바꾸는건 복잡하기만 하고 굳이 알아야 할 필요가 없으므로(컴퓨터가 하는 일입니다) 궁금하신 분은 각자 찾아보시기 바랍니다.

 여기서 중요한 점은, 실수는 정확하지 않다라는 점입니다.
 이번에는 부동소수점의 가수부를 어떻게 기억할 것인지 생각해봅시다. 자릿수를 표기하는 방법은 예전에 배운 적이 있을 지도 모릅니다.

 예를 들어,
  • 3.14 = 3 x 10^0 + 1 x 10^(-1) + 4 x 10^(-2)
 라고 표현할 수 있습니다.

 실제로는 이진수이기 때문에, 이렇게 됩니다.
  • .1011 = 1 x 2^(-1) + 0 x 2^(-2) + 1 x 2^(-3) + 1 x 2^(-4)


 이걸 어떻게 이해해야 하냐면, 3.14를 십진수로 표현하는 것은 이렇습니다.
  • 3 -> 3.1 -> 3.14
 표현하고자 하는 숫자에 '점점 가까워지도록', 더 작은 자릿수를 보태나가는 겁니다.

 원주율 pi는 무리수이기 때문에, pi를 표현하려면 3.14 정도까지 적어도 꽤 비슷한 숫자가 되지만, '완전히 같은 수'가 되려면 한없이 적어나가야 합니다.
 중간에 멈추면 '매우 비슷한 수'가 될지는 몰라도 '똑같은 수'는 아니라는 거죠.

 특히 부동소수점은 이진법을 쓰기 때문에, 반, 반의 반, 반의 반의 반을 보태는 식으로 숫자를 표현합니다. 따라서 십진법으로는 간단히 표시할 수 있는 숫자도 이진법으로는 정확히 표시할 수 없는 경우가 있습니다.

 수학적으로는 이진법이라도 '무한히 보태나가면' 정확하게 표현할 수 있지만, 말씀드렸다시피 컴퓨터로 그렇게 하려면 메모리도 '무한히' 필요한 법입니다. 당연히 불가능하고 창조에서의 실수는 64비트 안에서 어떻게든 끝내야 하기 때문에, 원래 의도했던 숫자와 컴퓨터의 부동소수점 표현은 차이가 있게 마련입니다.

 그러니까, 이렇게 생각해야 합니다. '실수'로 표시된 숫자는 그 숫자를 표시하는게 아니라, 그 숫자에 그나마 가까운 숫자를 표시한다 라고 말이죠.
 수학적는 수렴한다고 할 수 있습니다.
 실수형으로 표시한 1.0은, 정확히 1이란 숫자를 표현하는게 아니라, 64비트 안에서 1에 그나마 가까운 숫자를 표현한 것입니다.

 창조에서 1을 3으로 나누고, 다시 3을 곱했을 때 1이 나오는 것은 컴퓨터가 똑똑해서가 아닙니다. 왜냐하면, 1을 3으로 나누면 0.33333... 인데, 0.33333... 이란 숫자를 그대로 기억하는게 아니라 최대한 그에 가까운 숫자를 기억하고 있기 때문입니다.
 여기에 다시 3을 곱하면 수학적으로는 0.99999... 여야 하는데, 설사 그렇다 하더라도 부동소수점 범위 안에서 0.99999...를 표현하는 가장 가까운 수는 1이기 때문에, 오차 때문에 1이 되는 것 뿐입니다.
 (부동소수점 표현 자체가 오차를 내포하고 있기 때문에, 부동소수점 계산에서는 오차를 보정해주는 장치가 여럿 들어있습니다. 1/3에 3을 곱해서 1이 나오는 것은 그런 장치 때문입니다.)

 부동소수점 표현과 관련해서 유명한 말이 있습니다.
0과 0.0은 같지 않다.

 정수에서 0은 정확히 0을 표현하지만, 실수에서 말하는 0.0은 0에 최대한 가까운 수라는 뜻입니다.
 제가 위에서 창조의 실수는 지수부가 308 까지라고 말씀드렸죠?
 따라서 0.0도 0.0으로 표현하고, 0.1e-400도 0.0 으로 표현할 수 밖에 없습니다. 표시할 수 있는 가장 작은 숫자보다 작은 것을 표현하다보면 어쩔 수 없는 일입니다.
 다시 말해, 0.0이란 숫자는 0이 아니라, 0.1e-400 일 수도 있고, 3.14e-900 일 수도 있다는 것입니다. 즉 0.0이 표현하는 숫자는 무한히 많습니다. 그렇기 때문에 실수에서 어떤 숫자는 대충 그 근방의 값을 기억하고 있구나라고 생각해야 합니다. 실수는 정확하지 않습니다.
 (※주: 그렇긴 해도, 0이란 값만큼은 0을 가리키도록 되어 있습니다.)

 창조에선 부동소수점 타입의 실수만을 제공하기 때문에, 화폐 계산을 할 때 특히 조심하셔야 합니다. 애초에 실수가 정확한 값을 표시하는게 아니기 때문에, 10원도 틀리면 안 되는 화폐를 다루다보면 오차가 생길 수 있기 때문입니다.
 물론 가계부 프로그램 같은 걸 만들면 거기에서 사용하는 수가 '실수'로 커버되는 범위인 경우가 대부분이기 때문에 큰 문제가 생기지 않을 수도 있습니다.
 창조에선 선택의 여지가 없지만, 다른 언어에서는 화폐를 다룰 때 고정소수점을 사용합니다. 고정소수점을 표현하는 이름이 Currency인 이름이 그런 이유입니다.

 따라서, 만약 그런 데이터를 다룰 때에는 DB에서 부동소수점이 아닌, 고정소수점이나 정수 타입을 쓰셔야 합니다. 창조에는 '실수' 밖에 없기 때문에 선택의 여지가 없지만, 그렇다고 해서 다른 선택이 가능한 곳에서도 실수만 쓰시면 안 됩니다.



 '실수'가 왜 정확하지 않고, 그로 인해 발생할 수 있는 문제를 이해하는 것이 정확한 프로그램을 짜는데 도움이 될 거라 생각하여 적어보았습니다. 실수를 사용할 때는 이게 정확히 그 숫자를 표시하고 있는게 아니라는 점을 염두에 두는 것이 중요하다고 생각합니다.

 여기서 마치겠습니다. 바보같은 글 읽어주셔서 감사합니다.

바람   2012-01-04 AM 1:30:05  
긴글 쓰시느라 고생많으셨습니다.
글 정말 잘쓰시네요. 이해가 바로바로 됩니다.^^
지상현님 노고덕에 모르던 것 한가지 제대로 배워갑니다.^^
실수:=근사치;

지상현님 글 내용에 있는것처럼.. 많은 수학적 연산을 해야하는 곳에 '실수'를 사용하게끔 프로그래밍 했다면, 당연히 오차가 발생할 수밖에 없겠군요
LIST ALL               GO TO THE TOP


N
   Subject
Posted by
Date
H
119
   창조에서 반올림하기 [1]
지상현 2013/01/05  4984

   컴퓨터에서 소수점을 표기하는 방식에 대해 [1]
지상현 2012/01/03  7481
117
   창조의 변수형에 대한 고찰 [1]
지상현 2012/01/03  5761
116
   창조 초보자들을 위한 아주 기본적인 사용법
김대명 2011/03/09  6204
115
   객체 배열을 정복해보자! [1]
지상현 2010/06/28  6948
114
   [0강] 그림판에 그림을 그려보자!
박종훈 2009/10/24  6604
113
     [1강] 그림과 관련된 객체
박종훈 2009/10/24  5737
112
       [2강] ㅎ그림판에 그림을 그리기 위해 준비단계
박종훈 2009/10/24  5947
111
   [수정!] 직선, 사각형, 타원, 원, 호, 현을 그려보자! [4]
박종훈 2009/05/10  6640
110
     [0강] ㅎ배경의 좌표 체계에 대해서 알아보자! [2]
박종훈 2009/10/24  6999
109
       [1강] 직선을 그려보자!
박종훈 2009/10/24  7704
108
         [2강] 사각형을 그려보자!
박종훈 2009/10/24  5602
107
           [3강] 타원을 그려보자! (원 포함)
박종훈 2009/10/24  8351
106
             [4강] 현, 호를 그려보자! [4]
박종훈 2009/10/24  6244
105
     호현계산기2 Rev2 [6]
박종훈 2009/10/23  5852
104
   기타 자료실에 있는 다람쥐어 (파악해 보자_) [2]
김제형 2009/05/03  5756
103
   맞짱! 포인터(Pointer) - 3부 [창조에서 포인터를 사용해보자!] ... 제작중
박종훈 2009/02/26  5915
102
   맞짱! 포인터(Pointer) - 2부 [C언어 포인터 존재를 확인하자!]
박종훈 2009/02/26  7266
101
   맞짱! 포인터(Pointer) - 1부 [C언어 들춰보자!] [7]
박종훈 2009/02/26  6250
100
   자연수들의 합 쉽게 구하는 방법(수학과 프로그래밍) [7]
박종훈 2009/02/15  6104
99
   창조입문 : 메모장 만들기 [2]
신용주 2008/12/20  7526
98
   창조와 ActiveX (2)
지상현 2007/08/11  10770
97
   창조와 ActiveX (1)
지상현 2007/08/07  8254
96
   골칫거리 ㅎ사용자함수 DLL하나로 해결하기! [7]
박종훈 2007/06/23  7086
95
   환경파일로 파워유저되어보자![개정판] [예제/사용!] 2 [6]
박종훈 2007/01/02  7743
LIST ALL   1 [2][3][4][5] Next
Copyright 1999-2024 Zeroboard / skin by reedyfox in miniwini style
로그인
지우개 Expert 3.0
제작자 : 천호성 님 [LINK]
로그인
대박로또2005
제작자 : 최재일 님 [LINK]
로그인
1박종훈15292 점
2지상현8809 점
3손상진7388 점
4권선중6060 점
5이진백5174 점
로그인
가입일닉네임
05/31김동률
03/31홍형기
09/01o00pp99oo
12/27이재민
11/20이희철
로그인