한줄요약
CPP의 cmath.h의 round 함수는 Half away from zero 방식으로 구현되어있고, 이게 우리가 보통 생각하는 것과 비슷한 방식이다.
Python의 round 함수는 Half to even 형식으로 구현되어있다. 결과값이 다를수 있다
우리가 보통 생각하는 반올림의 개념은, 실수를 가장 가까운 정수값으로 변환해주는 것이다.
그리고 소수부가 0.5인 경우에는, 올림이 적용되는 것을 생각하는 것이 일반적이다 (1.5 ⇒ 2, 2.5 ⇒ 3, …). 사사오입이라고 부른다.
하지만, 사실 반올림에는 유일한 한가지의 올바른 방법이 있는게 아니라, 다양한 방법이 존재한다..
우선 보통 반올림에 해당하는 영어표현이라고 생각하는 rounding은 사실 그냥 수를 좀더 근사치로 변환하는 것을 전부 포함하는 말이다. 올림이나 내림도 다 rounding이다. 그러면 반올림에 정확히 대응하는 표현은 rounding to nearest integer이다.
소수부가 0.5인 경우가 아니라면, 가장 가까운 정수값으로 변환하는 것은 항상 유일하다. 하지만 소수부가 0.5일 경우에는 가장 가까운 정수값이 두개이므로 어느쪽으로 맞출지를 선택해야 하는데, 여기에는 다양한 방법이 있다.
-
원래 값 | 1.5 | 0.5 | -0.5 | -1.5 |
Rounding half up (사사오입) | 2.0 | 1.0 | 0.0 | -1.0 |
Rounding half down | 1.0 | 0.0 | -1.0 | -2.0 |
Rounding half toward zero | 1.0 | 0.0 | 0.0 | -1.0 |
Rounding half away from zero (cpp 기본방식) | 2.0 | 1.0 | -1.0 | -2.0 |
Rounding half to even (Python 기본방식) | 2.0 | 0.0 | 0.0 | 2.0 |
Rounding half to odd | 1.0 | 1.0 | -1.0 | -1.0 |
양수 범위에서만 처리하게 된다면 Rounding half up과 Rounding half away from zero 은 동일하고, Rounding half down과 Rounding half toward zero도 동일하다
decimal 모듈을 쓰게 된다면, 어떤 방식의 rounding을 사용할 것인지도 지정해줄수 있다
문제에서 반올림을 하라고 한다면, 원래는 어떤 형식의 반올림을 하라는 것인지 정확하게 지정해줘야 한다.
하지만, 일반적으로 생각하는 반올림은 사사오입 반올림이고, cpp의 내장함수도 양수범위에서는 동일하게 동작하다 보니, 별 생각 없이 반올림 방식에 대한 설명이 생략되는 경우도 있다. 이 경우는 알아서 적절한 반올림을 구현해서 처리해줘야 한다.
def round_half_up(x):
if x > 0:
return int(x) + 1 if x - int(x) >= 0.5 else int(x)
else:
return int(x) - 1 if int(x) - x >= 0.5 else int(x)