최대 1 분 소요


python round 함수의 문제

사사오입과 오사오입

  • 사사오입: 일반적으로 사용하는 반올림 방법이다. 4 이하의 숫자는 내림, 5 이상의 숫자는 올린다.

  • 오사오입(round-to-nearest-even): 파이썬에서 기본적으로 적용되어 있는 방법이다. 5 미만의 숫자는 내림, 5 초과의 숫자는 올린다.
    5일 경우에는 해당 숫자의 앞자리가 짝수면 내림, 홀수면 올린다.
    이 방법이 오차가 적은 반올림 방법이라고 할 수 있다.

In [1]:
print(round(0.5))
print(round(1.5))
print(round(2.5))
print(round(3.5))
Out [1]:
0
2
2
4

사사오입 반올림 함수

실생활에서 자주 사용되는 사사오입 반올림을 적용하기 위해 함수를 작성했다.

In [2]:
def roundTraditional(val, digits=1):
    return round(val+10**(-len(str(val))-1), digits)
In [3]:
print(roundTraditional(0.5))
print(roundTraditional(1.5))
print(roundTraditional(2.5))
print(roundTraditional(3.5))
print(roundTraditional(1.499999999999999, 0))
print(roundTraditional(1.4999999999999999, 0))
Out [3]:
0.5
1.5
2.5
3.5
1.0
2.0

하지만 5번째와 6번째는 둘다 1이 출력되지 않았다. 이는 파이썬에서 실수 자료형 float을 다룰 때 발생하는 부동 소수점 문제이다.

부동소수점 반올림

아래의 반올림들은 오사오입으로도 설명할 수 없다.

In [4]:
print(round(0.05, 1))
print(round(0.15, 1))
print(round(0.25, 1))
print(round(0.36, 1))
Out [4]:
0.1
0.1
0.2
0.4

해당 문제가 발생하는 원인은 ‘파이썬 부동소수점 오차’로 찾아보자.

decimal 모듈 사용

decimal 모듈에는 회계 응용 프로그램 및 고정밀 응용 프로그램에 적합한 십진 산술이 구현되어 있다.
매개변수로 문자열을 입력해야 한다.

In [5]:
import decimal

context = decimal.getcontext() # 산술 연산을 위한 환경설정
context.rounding = decimal.ROUND_HALF_UP # 사사오입으로 변경
                # decimal.ROUND_HALF_EVEN: 기본 오사오입
In [6]:
print(round(decimal.Decimal("1.499999999999999")))
print(round(decimal.Decimal("1.4999999999999999")))
print(round(decimal.Decimal("1.5")))
print(round(decimal.Decimal("0.15"), 1))
Out [6]:
1
1
2
0.2

Reference

댓글남기기