round()
파이썬의 내장 함수인 round()를 이용하다가 흥미로운 점을 발견했다. 0.5을 소수점 첫째자리에서 반올림하면, 1이 되는 것이 상식으로 통한다. 하지만 파이썬에서는 그 답이 0이 된다.
~ python
>>> f = 0.5
>>> round(f)
0
반올림을 이용한 백준 문제(18110 solved.ac) - https://www.acmicpc.net/problem/18110
18110번: solved.ac
5명의 15%는 0.75명으로, 이를 반올림하면 1명이다. 따라서 solved.ac는 가장 높은 난이도 의견과 가장 낮은 난이도 의견을 하나씩 제외하고, {5, 5, 7}에 대한 평균으로 문제 난이도를 결정한다.
www.acmicpc.net
은행원의 반올림(Banker's Rounding)
파이썬이 이런 특이한 반올림을 하는 이유는 '은행원의 반올림'이라는 반올림 규칙을 이용하기 때문이다. 은행원의 반올림(Banker's Rounding)은 은행에서 사용하는 반올림 방법으로, x.5를 반올림할 때 가까운 짝수로 반올림하는 방법이다. 절반(x.5)을 짝수로 반올림한다고 하여 Half-even Rounding이라고도 한다. 이와 반대로, 우리가 이해하고 있는 수학에서의 반올림 방법을 Half-up Rounding이라고 한다.
round(number, ndigits=None)
For the built-in types supporting round(), values are rounded to the closest multiple of 10 to the power minus ndigits
; if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2). Any integer value is valid for ndigits (positive, zero, or negative). The return value is an integer if ndigits is omitted or None. Otherwise, the return value has the same type as number.
https://docs.python.org/3/library/functions.html?highlight=round#round
이 규칙을 적용해서 반올림하면 다음과 같다.
~ python
>>> f = 0.5
>>> round(f)
0
>>> f = 1.5
>>> round(f)
2
>>> f = 2.5
>>> round(f)
2
decimal 모듈
decimal 모듈은 부동 소수점(Floating Point)에서 발생할 수 있는 산술 오류를 해결하고, 고정 소수점을 지원하는 모듈이다. 특히, 인간이 이해하는 수학적 관점에서의 연산을 그대로 재현해준다.
Decimal “is based on a floating-point model which was designed with people in mind, and necessarily has a paramount guiding principle – computers must provide an arithmetic that works in the same way as the arithmetic that people learn at school.” – excerpt from the decimal arithmetic specification.
https://docs.python.org/3/library/decimal.html#module-decimal
물론, 반올림에 대한 연산도 지원한다. 이를 이용해 우리가 이해하고 있는 반올림 방법을 구현하면 다음과 같다.
~ python
>>> from decimal import *
>>> getcontext().rounding = ROUND_HALF_UP
>>> Decimal('2.5').quantize(Decimal('1.'))
Decimal('3')