0. 개요

Garbage in, Garbage out.
올바르지 않은 입력값을 넣으면 올바르지 않은 출력값이 나온다. 

라는 IT의 속담이 있다.

대학교 1학년때, C언어 강의를 들을 때 교수님이 저런 말을 하면서,

니들이 오타낸거 아니냐?

 

를 예쁘게 돌려 말했던 기억이 난다.

1. 컴퓨터가 틀렸다?

소숫점 계산을 배운 초등학생에게 1.1 + 0.1을 물어보면, 너무나도 당연하게도 1.2라고 대답 할 것이다.

하지만, 파이썬에서 1.1 + 0.1 == 1.2 를 입력하면, False를 대답한다!

그럼 왜 이런 결과를 내는걸까?

 

2. 2진법

컴퓨터는 0과 1로 이루어져있고, 숫자를 표현하기 위해 2진법을 사용한다.

예를들어, 8칸짜리 공간이 있다고하면 

2진법의 (00000010) 은 10진법의 (2)와 같다.

그렇다면, 만약 8칸짜리 공간에서 마이너스를 표현하고싶다면?

 

3. 부호

8칸의 공간에서 마이너스를 쓰고싶다면, 한칸을 마이너스와 플러스를 구분하는 숫자로 "약속" 하면 된다.

0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1

제일 앞의 숫자를, "부호" 라고 약속하는 것이다. 0 = +, 1 =  -

약속을 하기 전에는 2의 8승 만큼 표현이 가능했는데,

약속을 한 이후에는, 마이너스로 2의 7승, 플러스로 2의 7승만큼 표현이 가능해졌다!

이 기세로, 소수점도 표현해보려고한다면?

 

4. 소수점

정수는 2진법으로 쉽게 표현할 수 있지만, 소수점을 2진법으로 표현하기에는 어려움이 있다.

마치 10진법에서도 1/3을 소수점으로 표현할 때 0.33333333...... 같은 순환소수가 있듯, 2진법에도 표현하려고 하면 끝없이 반복되는 케이스가 있곤 하다.

그래서, 숫자를 표현할 때, 부동소수점 이라는 방식을 사용한다.

너무 어려운 내용이라 담지는 않았다!

대충 이해한 바로는, 그 숫자와 가장 근사값을 찾는 방식으로 작동된다고 한다.

따라서, 정확한 값을 출력해주지는 못하고, 0.1이 0.100000000000000001 같은, 아주 작은 오차가 발생하곤 한다.

그래서 0.1 + 1.1을 했을 때 1.2가 아닌 1.200000001과 같은 아주 작은 오차가 발생한다.

 

5. 문제

이렇게 작은 오차가, 실제로 문제를 일으킬 수 있다.

예를 들자면,

  • 재료 양에 따라 확률이 정해지는 게임 강화 시스템에서, 100%를 채웠는데 사실 100%가 아닌 99.99999%여서 실패함
  • 금융권에서, 0.1달러를 송금 후 다시 받을 때마다 0.00001달러가 더 들어옴
  • 의료용 기기를 만드는데, 소수점 단위로 정밀 의료 용품을 만들었는데 고장나버림

이런 이슈가 있을 수도 있을 것 같다! (금융과 의료는 좀 과장된 내용일수도 ?)

그렇다면, 소프트웨어 QA의 입장에서 이러한 문제를 발견했을 때 어떻게 해야 할까?

 

6. 해결

실무에서는, 정말 단순한데 너무나도 확실한 방법을 사용한다.

실무자 : 그냥 소수점 안쓰지 뭐 ㅋㅋ

 

실제로, 대부분의 실무에서는 이러한 방법을 사용한다고 한다.

즉, 100프로가 백만이라면 50%의 확률을 구현할 때 50만을 쓰는 방식으로 구현한다.

꼭 소수점을 써야하는 상황이라면, 파이썬으로 치면 round와 같은 반올림 함수를 사용해서 사용하는 것을 권한다고 한다.

7. 결론

사실 너무나도 유명한 내용이기에 실무에서 이런걸 마주할 일은 없을 것 같다.

하지만, 자동화 스크립트를 만든다고 할 때, 소수점을 쓸 일이 있다면 한번은 생각하고 쓸 수 있는 내용이다.

또한 만약 누군가가 소수점을 사용해서 코드를 짜는걸 발견 한다면, 취약점을 훈수할 생각에 입꼬리가 씰룩거릴 수도 있다.

 

8. 세줄 요약

1. 컴퓨터에 소수점을 넣으면 가끔은 근사 값을 준다.

2. 그냥 정수로 바꿔 쓰면 마음 편하다.

3. 사실 실무에서는 볼 일 없는 문제일 것 같다. 다 정수로 쓰고있거나 반올림 처리 하고 있거나.

+ Recent posts