[기본원리] 소수점 때문에 바보가 되는 컴퓨터??

반응형





실제로 컴퓨터는 정확하고 정밀한 기계이지요.
따라서 " 컴퓨터는 거짓말을 하지 않는다!! " 라고 흔히들 말하지만,
실제로 그렇지 않은 경우도 있습니다.
그 중 하나가 바로 소수를 계산하는 경우인데요,

따라서 소수의 계산과정을 이해하면 원하지 않는 결과를 보거나
친구에게 빌려준 돈을 제대로 계산하여 손해없이 받을 지도 모릅니다 ㅋㅋ

읽기전에 손가락 한번 클릭~ >_<

고마워요 ~ Chu ~ ♥




테스트 코드

소수관련 문제에서 많은 서적들에서 언급하던 0.1을 100번 더하는 프로그램이 있습니다.
저도 한번 사골국물로 우려먹어 볼까 합니다 ㅎ

실제 0.1을 100번 더하면  10  이 됩니다. 당연하지요?
하지만 암산 말고 아래의 코드를 보세요.

< 0.1을 100번 더하는 프로그램 >

분명 0.1을 100번 더했음에도 불구하고 9.9999... 라는 결과가 나왔습니다.
왜 10이 되지 않을까요?

이런 현상은 컴퓨터가 2진수만 사용하는데 있어서 소수처리가 안되는것이 있기 때문입니다.
그럼 이제 컴퓨터 내부에서는 소수를 어떻게 처리하는지 알아보지요.


소수점 이하를 2진수로 바꿀 때

컴퓨터 내부에서는 모든 정보를 2진수로 처리합니다.
예를들어 2진소수  '  1011.0011 ' 있다면  이것을 10진수로 바꾸고 싶습니다.
어떻게 하면 될까요?

방법은 이렇습니다.

  • 우선 정수 부분은 각 숫자에 '자릿수' 를 곱해 줍니다.
  • 소수점 이하 부분은 ' -제곱 ' 으로 곱해주면 됩니다.
글로만 봐선 어렵기 때문에 아래 그림을 보세요.



이런식으로 처리됩니다.

따라서 2진수 소수점 0.1은 얼마가 되지요?
  • 2진수 0.1은  10진수 0.5
  • 2진수 0.01은  10진수 0.25
  • 2진수 0.001은  10진수 0.125
  • 2진수 0.0001은  10진수 0.0625   .....

순으로 됩니다.

결국 ' 1011.0011 ' 을 10진수로 변환한것은  11.1875 라는 값이 나오게 됩니다.

컴퓨터가 계산을 틀린 이유

똑똑하고 빠른 컴퓨터가 계산을 틀린 이유는 10진수의 소수중에 2진수로는 바꿀 수 없는 것이 있기 때문입니다.
예를들어 10진수 0.1은 2진수로 얼마가 될까요?

빠르게 말해보자면 10진수 0.1은 2진수로 절대로 정확하게 바꿀 수 없습니다.
소수점 이하 자릿수가 아무리 많더라도 말이지요.ㅎ

짧게 소수점 이하 4자리만 생각해보지요.
2진수로 나타내는 범위는  0.0000 ~ 0.1111 까지가 되는데요,
따라서 10진수에 대응되는 0.5, 0.25, 0.125, 0.0625 의 4개의 값의 조합만으로 밖에 표시할 수 없다는 뜻입니다.  이것만으로 보면 0과 0.0625 사이의 값은 표현이 불가능 하다는 말이지요.
또한 0.0625 다음에 바로 0.125 가 나오므로 0.1을 딱 만드는것이 불가능 하게 되어 버립니다.


순환소수

10진수 10을 3으로 나누면 값이 얼마일까요?
0.3333....  처럼 무한반복되는 것을 순환소수 라고 부릅니다.

이런 순환소수를 컴퓨터는 처리하지 못하지요.
실제로 10진수의 0.1을 2진수로 바꾸어 보게되면은,
0.00011001100 ....  처럼 순환소수가 되는데요,
때문에 0.1을 100번 더한다고 해도 10이 되지 않을 것입니다.

즉, 데이터형의 범위에 맞게  0.333... 같은 순환소수를 0.333 처럼 딱 짤라서
만들어 버리기 대문에 여기에 3을 곱해도 ( 0.3333 X 3 ) 10이 되지 않는 것과 마찬가지 입니다.



틀린 계산 예방하기

결국 계산을 틀리게 하는 원인은 내부에서 소수가 부동소수로 취급되기 때문입니다.
[ 부동소수는 추가로 정규표현과 익세스 표현, 단정도, 배정도가 있어서 길어질 것같아 다음 포스팅으로 밀어 버렸습니다 ^^; ]

아무튼 계산 오차를 예방하려면 ' 소수를 정수로 바꾼 뒤에 계산 ' 해야 합니다.
컴퓨터는 정수값의 계산은 틀리지 않기 때문이지요 . ㅎ ( 물론, 데이터형의 범위 내에서만요..ㅎ)
계산 처리시에만 일시적으로 정수로 바꾼 뒤에 마지막에 다시 소수로 변환해서 나타내면 됩니다.


이처럼 0.1을 10배하여 정수 1로 바꿔 준 후에,
1을 100번 더하고 난 다음 다시 10으로 나누면 되지요 ^^;

이렇게 간단한걸 왜이렇게 길게 글을 썻냐구요?
공부하기 위해서지요 뭐 ...ㅋㅋ




반응형

댓글(10)

  • 2010.07.12 22:50 신고

    전공 수업때 봤었던 내용같은데 부동소수점이랑 비트표기방식 때문에 발생하는 오류로 기억하고 있는데 맞나요?ㅋㅋㅋ

    • 2010.07.13 11:44 신고

      안녕하세요 호환님 ^^ 반가워요 ㅎ
      프로젝트 순조롭게 되고 계신가요 ?ㅎ

      우어..전공수업....
      저도 아마도 전공수업때 들었겠으나,
      기억이 도무지 나질 않네요 ;;;
      그땐 도대체 콩인지 된장인지도 모르고
      그냥 그런가부다 하고 넘어가 버린 기억만 있네요 ㅋ

      이제야 조금 눈이 트인 느낌이라
      따로 처음부터 공부해보고 있는데 새롭습니다 ㅎ

      그나저나 그때 제대로 해둘껄 ㅠㅠㅠ

  • 2010.07.12 23:30

    새로운 사실을 알았네요... 와우!

    • 2010.07.13 11:54 신고

      알면 알수록 더욱더 심오해 지는것이
      또한 컴퓨터 계열인거 같습니다 ㅎㅎㅎ

  • 비세리스
    2010.08.03 17:15

    그냥 취미삼아서 게임 공식 계산하는 중에 배워갑니다.

  • 2011.04.07 23:25 신고

    저도 전산과출신인데, 예전 기억 더듬으면서 검색하다가 오게 되었습니다.

    글 내용들이 머리속에 쏙쏙 들어오네요. ㅋㅋ

  • 수학
    2013.03.27 23:40

    수학에선 9.99999...=10으로 처리합니다.

    그리고 0.1을 나타내려면 밑이 2인 로그를 써서 로그를 하나의 기호로잡고 내부 계산을하면 틀리지 않습니다.

    • 수학2
      2022.06.13 16:51

      관리자의 승인을 기다리고 있는 댓글입니다

Designed by JB FACTORY