보다 정확한 숫자 계산
8퍼센트 이호성
- Python 3.6 을 기준으로 작성 되었습니다.
- 질문은 발표가 끝나고 한꺼번에 받겠습니다.
-
http://slides.com/hosunglee-1/deck-10/live#/
에서 함께 보실 수 있습니다
누구세요?
이호성
- 8퍼센트(언제나 개발자 채용중) CTO
프로덕트 팀 블로그, 브런치 - 엔써즈 DevOps 팀
- Python 10년차
- 함께하는 개발
- 글쓰기: 개인 블로그, 브런치
- 2014 PyCon 구경
- 2015 PyCon 발표(Python 테스트 시작하기)
- 2016 PyCon 티셔츠 받고 유아교육전
- 2017 PyCon 즐겨요!
오늘 발표의 목적은?
-
숫자 계산이 의도와 다른 이유와 대안
-
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.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,297