*이 글을 읽기전에 작성자 개인의견이 있으니, 다른 블로그와 교차로 읽는것을 권장합니다.*
과제: 1.0+1.1==2가 False가 나오는 이유?
프로그래밍에서 1+1 == 2가 나온다. 이는 1과 1이 모두 정수형(integar)이기에 같은 정수형인 2가 나옵니다. 그렇다면 0.1+ 1.1 == 1.2가 나올까? 0.1과 1.1 모두 float(실수형) 자료형입니다.
1.200...이 나온다. 왜 저렇게 나오는 것일까?
문제원인?
이는 컴퓨터의 부동소수점의 표현방식에서 찾을 수 있습니다. 부동소수점이란? 컴퓨터에서 실수(float)를 표현할 때, 소수점의 위치를 고정하지 않고, 따로 적어내는 방식으로, 유효숫자를 나타내는 가수와 소수점 위치를 풀이하는 지수 부분으로 나뉘며, 십진법(decimal)을 이진법으로 표현하는데 있어서 근삿값으로 표현한 방식.(부동소수점의 다른 말로 '떠돌이 소수점'이라 한다.) 이는 부동소수점이 고정소수점(소수점 위치를 고정하는 방식)보다 더 넓은 범위의 수를 표현할 수 있다는 장점에 있습니다.
부동소수점 표현방식은 (가수)×(밑수)^(지수) 이뤄집니다. 예를 들어 0.4를 밑수10으로 표현하면 0.04*10^1로 표합니다. 밑수를 2로 표현하면 0.8*2^-1으로 표기하는데, 가수를 자연수 4로 바꾼다면 4*10^-1으로 표기합니다. 이때, 가수를 자연수 1자리로 표기하는걸 정규화(normalization)라고 합니다. 십진법으로 표기한다면 0.04*10^1으로 표기할것을 정규화방식으로 4*10^-1로 표기한다면 메모리사용량을 줄일 수 있습니다. 컴퓨터에서는 밑수가 10일 경우 e를 사용하는데, 0.4는 4e-1 또는 0.04e+1로 표현할 수 있습니다.
문제파악
컴퓨터의 숫자는 10진법(decimal)의 내용을 가지고 있더라도 표현방식이 2진법에 있기 때문에, 십진법 숫자는 2진법의 숫자형태로 근사되어 처리(계산)합니다. 즉, 우리는 밑수가 10이 아닌, 2의 형태로 계산하려다 보니 실수값을 십진법만큼 정확히 표현하지 못하고, 반올림해서 2진법으로 근사하여 처리된 결과값을 보고 있는것입니다. 그렇다면 0.1+1.1 ==1.2라는 코드를 십진법(decimal)로 정확히 계산할 수 없을까?
해결방법
decimal.Decimal, math.fsum(), round(), float.as_integer_ratio(), math.is_close() 여러 방식이 있지만, 그중 가장 대중적인 decimal 라이브러리를 활용해서 해결해봅니다.
# 부동소수점(가수,지수) 문제 해결하기
# 부동소수점은 밑수가 10인 실수를 밑수가 2로 근사하여 계산하다 나온 오류
from decimal import Decimal
Decimal('0.1')+Decimal('1.1')
float(Decimal('0.1')+Decimal('1.1')) == 1.2
부동소수점 문제를 decimal 라이브러리를 이용해 해결했습니다.
위 문제사례를 통해 앞으로 /(나눗셈)연산자의 결과값이 실수로 나오는 이유가 부동소수점이라고 알아봤습니다. 앞으로 나눗셈 연산자의 결과가 실수형이 나오는 이유는 컴퓨터가 십진수를 이진수 비트로 표현하는 과정에서 나오는 부동소수점 근사값 원인이라고 얘기할 수 있습니다.
'Python 기초' 카테고리의 다른 글
파이썬 기초(5)-튜플(Tuple) 자료형 (0) | 2024.03.13 |
---|---|
파이썬 기초(4)-컬렉션 타입과 리스트(List) 자료형 (0) | 2024.03.13 |
파이썬 기초(3)-문자열과 메서드(Method) (0) | 2024.03.12 |
파이썬 기초(2)-변수에 관해서 (0) | 2024.03.12 |
파이썬 기초(1)-print()함수과 출력서식 (0) | 2024.03.12 |