보다 정확한 숫자 계산

8퍼센트 이호성

누구세요?

  이호성

오늘 발표의 목적은?

  • 숫자 계산이 의도와 다른 이유와 대안

  • Python 공식문서를 찾아가며 문제 해결 하기

  • 컴공과 첫 과목의 향수

Back to the basic

Rounding

11원을 두 명에게 나눠 주려면?

0.5원은 돌려 줄 수가 없어요

제 0.5원을 왜 떼 먹나요?

이번에는 13원의 이자를 나눠줍시다.

응?

공식 문서를 찾아봅시다.

Text

If two multiples are equally close, rounding is done toward the even choice.

Rounding 

Default 의 변경은 Python 3.0 부터 (What's New In Python 3.0)

Banker's Rounding

가까운 수로 맞추되 정확히 절반인 경우 짝수로 맞춘다.

  • 실제로 은행에서 사용 되는 방식
  • 한쪽으로 치우치지 않는 가장 공평한 방법
  • (하지만 학교에서 배운것과는 다른 방법)

Floating Point

다시 Round

왜 2.68이 되지 않는걸까?

다시 공식문서의 확인

The behavior of round() for floats can be surprising.

float 가 문제가 된다고?

부동 소수점의 표현

진법 표현 계산
10진법 0.125  1/10 + 2/100 + 5/1000
2진법 0.001  0/2 + 0/4 + 1/8 
  • 1/3 은 10진법으로 어떻게 표현될까? 0.3333333...
  • 0.1 은 2진법으로 어떻게 표현될까? 0.000110011001100110011...

IEEE 754

Double-precision floating-point format

부호

지수

가수

IEEE 754로 0.1표시

진법 부호 지수 가수 계산
10진법 + -1 1.0
2진법 + -4 1.6
+1.0 * 10^{-1} = 0.1
+1.6 * 2^{-4} = 0.1

물론 1.6에 가까운 근사값 입니다.

그런데 출력은 왜 0.1로 할까?

Python 3.1 부터 가장 짧은 표현을 사용

(내가 의도한) 0.1이 (실제로 저장되는) 0.1이 아니라면서
왜 0.1을 보여주는 거죠? 

 확인

같은수 인가?

출력해 보자

비교의 문제

 이미 값의 저장시에 오차가 발생 했기 때문에
정확한 비교를 할 수 없다.

Python 실망이야!

언어의 문제가 아닙니다. 

 보다 정확한 비교를 위한 대안

 테스트시에는 unittest.TestCase.assertAlmostEqual 을 사용

round의 사용

 isclose 사용

decimal

decimal의 목적

컴퓨터는 사람들이 학교에서 배우는 것과 동일한 연산 방식을 제공해야 한다.

  • round(2.5) = 3
  • round(2.675, 2) = 2.68
  • 0.1 + 0.1 + 0.1 - 0.3 = 0 
  • 1.30 + 1.20 = 2.50

Decimal 동작 원리

Context

Rounding modes

Rounding을 (내 마음대로) 다시 한번!

Signals

이름 조건
Inexact 계산 결과가 정확하지 않을 때
Rounded 유효숫자의 수가  줄어 들었을 때
FloatOperation Decimal과  float가 함께 사용되었을 때

 계산 과정에서 조건에 따라 Signal이 발생하고, 그 결과 관련된 flag를
설정하거나 trap(Exception)을 발생 시킵니다. 

그 외에도 여러가지 Signal 이 있습니다.

Traps

의도되지 않은 연산이 일어났을 때 Exception 을 발생 시킨다. 

Flags

Text

  • Inexact: 계산의 결과가 반올림이 되면서 정확하지 않게 되었음
  • Rounded: 소수점 아래 9자리에서 반올림 되었음

요약

의도 하지 않은 연산이 되는 경우 

  • Rounding 규칙이 다른 경우
  • float 로 저장이 되면서 10진수가 정확히 표현되지 않는 경우
  • 저장에서 오차가 생기면서 저장된 값의 연산과 비교에도 문제가 생긴다. 

정확한 계산이 필요한 경우 decimal을 사용하자!

  • Rounding 규칙을 지정할 수 있다.
  • 원하는 정확도로 보다 정확한 계산을 할 수 있다.
  • 계산에 오차/오류가 생겼을 때 이를 정확히 인지할 수 있다. 

 참고 자료

 감사합니다.

열린 공간에서 이야기 나눠요

208B

4시

보다 정확한 숫자 계산

By Ho Sung Lee

보다 정확한 숫자 계산

PyCon Korea 2017 발표 자료입니다.

  • 7,373