C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[25411] [자료] 카이스트 C뉴스그룹의에 김승범님이 올리신 글의 일부입니다.
정성훈.해미 [sage5nor] 1329 읽음    2003-04-29 14:32
서동영 wrote:
>
> 궁금한게 있네요.
> 120000정도하고 0.04를 곱했더니 오차가 생기더군요.

저는 테스트해봤는데 정확히 48000이라고 찍히던데요? :)

> 어떻게 내부적으로 처리되고 오차가 생기는 이유를 알고 싶군요.
> double형으로 선언하면 오차가 생기지 않던데
> 제 생각엔 할당된 메모리 크기 차이 때문이라고 생각되는데
> 어떻게 내부적으로 처리되어서 오차가 생기는 건지 알고
> 싶습니다.
> 고맙습니다. 읽어 주셔서. 답변 부탁드립니다. 무지한 소생에게....

예, 물론 double과 float는 차지하는 메모리 크기가 다르고 이에 따라
오차의 정도도 달라질 수 있습니다.

하지만 현재 쓰이는 부동소수점 표현 방식으로는 아무리 큰 데이터형을
쓰더라도 0.04와 같은 값을 정확히(exactly) 표현할 수는 없고 어느
정도의 오차는 생기게 됩니다. 연산 과정에서의 오차가 아니라, 실수를
표현하는 방법 자체에서 오차가 생긴다는 겁니다.

실수가 표현되고 저장되는 방법은, 실수를 이진수로 0.nnnn.. * 2^mm
(또는 1.nnnn.. * 2^mm)과 같이 나타낸 후 nnnn, mm 부분을 저장하는
것입니다. double, float 등의 형이 차이가 나는 것은 이 nnnn.. 부분을
몇 자리까지 표현하는가, 그리고 mm이 가질 수 있는 범위가 얼마나 큰가에
따른 것입니다.

그런데 여기서 nnnn.. 부분이 유한하게 표현된다면 컴퓨터에서 정확히
표현할 수 있는 실수가 되지만, 무한히 반복된다면 정확히 표현할 수
없는 실수가 됩니다.

예를 들어, 0.5는 이진수로 0.1이므로 오차 없이 정확히 표현될 수
있습니다. 하지만 0.1은 1/10이고, 이는 이진수로 표현할 경우
0.0001100110011..과 같이 무한히 반복되는 수가 되고, 이를 유한한
자리수로 표현하려면 어딘가에서 잘라서 저장해야 하는데 이것이
오차의 근본 원인이 됩니다.

여기서 볼 수 있듯이 십진수로는 0.1과 같이 간단히 표현되는 수라도
이진수로는 그렇지 않은 경우가 있으며, 이를 간과하고 루프를 돌면서
x += 0.1; 등의 연산을 계속한다면 작은 오차가 쌓여서 무시할 수
없는 결과를 낳을 수 있지요.

다만, 실수로 연산을 하여 화면에 출력했을 때 대부분의 경우 오차를
느낄 수 없는 것은, 잘려 나간 자리쪽에서 반올림 등을 하여 결과를
표시하기 때문입니다. 즉, 실제로는 1.49999999999999와 같이 저장된
값이라도 1.5라고 표시하는 것이지요. 대부분의 경우에 그렇게 하는
것이 올바른 결과를 주기 때문입니다. (단 데이터형의 크기가 클수록
반올림되는 자리도 소수점에서 더 멀리 아래로 내려가겠지요.)

더 자세한 것을 알고 싶으시면 computer arithmetic, IEEE floating-
point number representation  등에 관련된 책을 찾아 보세요.

--
김승범








tjlee 님이 쓰신 글 :
:
: 아래와 같이 하였을 때 c 와 d의 값이 다르게 나오는 이유는 무었일까요?
: c를 double로 하였을 때는 결과 동일함.
:
: // code
:
: #include <stdio.h>
: #include <conio.h>
:
: //---------------------------------------------------------------------------
: void main()
: {
:    int a = 8, b = 5, *p = &a, *q = &b;
:    float c;
:    double d;
:
:    c = (float) 8 * *p / *q + 15;
:    d = (float) 8 * *p / *q + 15;
:
:    printf(" c = %f\n", c);
:    printf(" d = %f\n", d);
:
:    getch();
: }
:
: // 결과
:  c = 27.799999
:  d = 27.800000

+ -

관련 글 리스트
25409 Quiz임다..... tjlee 775 2003/04/29
25411     [자료] 카이스트 C뉴스그룹의에 김승범님이 올리신 글의 일부입니다. 정성훈.해미 1329 2003/04/29
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.