어떤 프로그램 언어를 쓰든 0.1 + 0.2 ≠ 0.3 이 되는 것이 당연(?)합니다.
또한 1.0/(0.1 + 0.2 - 0.3) ≠ ∞ 이 되는 것도 당연(?)합니다.
>>> 0.1 + 0.2 - 0.3
5.551115123125783e-17
>>> 0.1 + 0.2 - 0.3 > 1.0E-17
True
>>> 0.1 + 0.2 - 0.3 > 1.0/10E17
True
0.1 + 0.2 - 0.3 이 1.0E-17 즉 0.000000000000000001 보다 크다고 합니다.
이래 가지고서는 부동소수점수의 계산 결과를 어디 까지 믿을 수
있는지 의문입니다.
(보통으로는 배정밀도 부동소수점수는 유효수자 개수가 14개~15개 정도입니다.)
다행히 Python 의 fractions 모듈과 decimal 모듈을 사용하면
이런 오류를 쉽게 복구할 수 있습니다.
아래는 Python 3 인터프리터로 실행한 결과입니다.
(fractions.Fraction 객체).limit_denominator() 가 문제 해결의 핵심입니다.
(조금 번거럽네요.)
>>> import fractions, decimal, math
>>> a = fractions.Fraction(0.1)
>>> b = fractions.Fraction(0.2)
>>> c = fractions.Fraction(0.3)
>>> a + b == c
False
>>> 0.1 + 0.2 == 0.3
False
>>> a + b > c
True
>>> 0.1 + 0.2 > 0.3
True
>>> a + b - c
Fraction(1, 36028797018963968)
>>> 0.1 + 0.2 - 0.3
5.551115123125783e-17
>>> a2 = a.limit_denominator()
>>> b2 = b.limit_denominator()
>>> c2 = c.limit_denominator()
>>> a2, b2, c2
(Fraction(1, 10), Fraction(1, 5), Fraction(3, 10))
>>> a, b, c
(Fraction(3602879701896397, 36028797018963968), Fraction(3602879701896397, 18014398509481984), Fraction(5404319552844595, 18014398509481984))
>>> a2 + b2
Fraction(3, 10)
>>> "%s" % (a2 + b2)
'3/10'
>>> print("%s" % (a2 + b2))
3/10
>>> c2
Fraction(3, 10)
>>> "%s" % (c2)
'3/10'
>>> print("%s" % (c2))
3/10
>>> a2 + b2 == c2
True
>>> a2 + b2 - c2
Fraction(0, 1)
>>> print(a2 + b2 - c2)
0
>>> print("%s" % (a2 + b2 - c2))
0
>>> print("%d" % (a2 + b2 - c2))
0
>>> print("%d" % (a2 + b2))
0
>>> print("%d" % (c2))
0
'프로그래밍 > Python' 카테고리의 다른 글
Python 언어에서 큰 부동소수점수(native double) 의 정확도 (0) | 2023.03.19 |
---|---|
Python의 math.floor() 함수에 대한 문제점(?) 고찰 (1) | 2023.01.11 |
wxPython을 이용한 간단한 웹 브라우저 소스 몇 가지 (0) | 2020.11.29 |
wxPython 4.1.1 (현재 최신 버전) 설치하기 (0) | 2020.11.28 |
PyGTK 릉 이용한 RPN 계산기 (0) | 2014.08.16 |