숫자 데이터를 사용하다보면 특정 자리수를 기준으로 나머지 자리수를 올림, 버림, 반올림해야하는 경우가 많다. 파이썬에서도 이런 연산들을 위한 함수들이 제공되고 있다.
숫자 올림
숫자의 올림은 구하려는 자리 미만의 수를 올려서 처리하는 방법이다. 예를 들어 1.2라는 숫자의 소수점 자리수를 올림하면 2가 된다. 0.2라는 숫자를 올림처리해서 1을 더해 2가 되는 것이다. 만약 2라는 숫자를 올림처리하면 여전히 2가 된다. 나머지 숫자가 없기 때문이다.
파이썬에서는 math 모듈에 있는 ceil() 함수를 통해 숫자를 올림처리할 수 있다. 예를 들어보자.
import math
print(math.ceil(3.3))
print(math.ceil(10.23))
print(math.ceil(-1.23))
print(math.ceil(7))
print(math.ceil(0))
# 4
# 11
# -1
# 7
# 0
math 모듈의 ceil() 함수를 다시 정의하면 '주어진 숫자와 같은 정수 혹은 주어진 숫자보다 큰 정수 중에 가장 작은 숫자'를 리턴한다.
따라서 7이나 0처럼 정수를 입력하면 그 숫자가 그대로 리턴된다. 양의 실수를 입력하면 그 숫자보다 큰 정수 중에 가장 작은 숫자를 리턴한다. 예를 들어, 3.3보다 큰 정수중에 가장 작은 수는 4다. -1.23보다 큰 정수중에 가장 작은 수는 -1 이다.
숫자 내림
숫자의 내림은 구하려는 자리 미만의 수를 버리는 방법이다. 예를 들어 1.2라는 숫자의 소수점 자리수인 0.2를 내리고 1이라는 숫자를 취하게 된다. 만약 2라는 숫자를 내림처리하면 여전히 2가 된다. 올림과 마찬가지로 나머지 숫자가 없기 때문이다.
파이썬에서는 math 모듈에 있는 floor() 함수를 통해 숫자를 내림처리할 수 있다. 예를 들어보자.
import math
print(math.floor(3.3))
print(math.floor(10.23))
print(math.floor(-1.23))
print(math.floor(7))
print(math.floor(0))
# 3
# 10
# -2
# 7
# 0
math 모듈의 floor() 함수를 다시 정의하면 '주어진 숫자와 같은 정수 혹은 주어진 숫자보다 작은 정수 중에 가장 큰 숫자'를 리턴한다.
올림과 마찬가지로 0이나 7같은 정수는 그 숫자 그대로 리턴된다. 양의 실수를 입력하면 소수점 자리를 버리고 정수 부분만 취한다. 예를 들어 3.3보다 작은 정수 중에 가장 큰 숫자는 3이다. -1.23보다 작은 정수 중에 가장 큰 정수는 -2다.
숫자 버림
숫자의 버림은 소수점 자리 숫자를 버리는 방법이다. 예를 들어 1.2라는 숫자의 소수점 자리수인 0.2를 버리면 1이라는 숫자를 취하게 된다.
파이썬에서는 math 모듈에 있는 trunc() 함수를 통해 숫자의 버림처리를 할 수 있다. 예를 들어보자.
import math
print(math.trunc(3.3))
print(math.trunc(10.23))
print(math.trunc(-1.23))
print(math.trunc(7))
print(math.trunc(0))
# 3
# 10
# -1
# 7
# 0
내림 연산과 다른점은 음수에서 등장한다. -1.23이라는 숫자를 내림하면 -2가 리턴되지만 버림하면 -1이 리턴된다.
숫자 반올림
숫자의 반올림은 특정 자리수를 기준으로 가장 가까운 정수를 리턴하는 방법이다. 예를 들어 1.2라는 숫자와 가장 가까운 숫자는 1이다. 1과는 0.2 차이고, 2와는 0.8차이니까 1이 더 가깝다. 마찬가지로 2.7을 반올림하면 3이 리턴된다. 3과는 0.3, 2와는 0.7차이이기 때문이다. 역시 정수를 입력하면 입력한 정수가 그대로 리턴된다.
파이썬에서는 round() 함수를 이용해서 반올림을 사용할 수 있다. 예를 들어보자.
import math
print(round(3.3))
print(round(10.23))
print(round(-1.73))
print(round(7))
print(round(0))
# 3
# 10
# -2
# 7
# 0
반올림은 특정 자리수를 기준으로 가장 가까운 정수를 리턴한다고 했다. 그렇다면 두 정수에 공평하게 가까운 1.5, 2.5 같은 숫자는 어떻게 반올림될까? 수학 시간에는 0.5는 올림쪽으로 반올림이 된다고 배웠다. 하지만 파이썬은 약간 다르다.
import math
print(round(1.5))
print(round(2.5))
print(round(-1.5))
print(round(-2.5))
print(round(0))
# 2
# 2
# -2
# -2
# 0
수학책에서 배운대로라면 2, 3, -2, -3이 나올 것 같다. 하지만 파이썬은 2, 2, -2, -2를 리턴한다. 전자의 방법을 사사오입(Round-off) 방식이라고 부르며, 후자의 방법을 오사오입(Round-to-nearest-even) 방식이라고 한다. 사사오입은 4까지는 버리고, 5부터 올림처리한다. 오사오입은 4까지는 버림, 6부터는 올림을 하고, 5인 경우에는 앞자리가 홀수인 경우 올림, 짝수인 경우 버림한다.
파이썬은 오사오입 방식의 반올림을 지원한다. 그래서 파이썬의 반올림 방식에 대해 정확하게 이해하고 코드를 작성해야한다. 반올림이 들어가는 로직에서 사사오입을 가정하고 작성되었는데 실제로는 오사오입으로 계산되어 문제가 발생할 가능성도 있기 때문이다.
소수점 반올림
파이썬의 round() 함수는 두 번째 인자를 받을 수 있다. round() 함수가 받을 수 있는 두번째 인자는 반올림의 정밀도와 관련된 내용이다. 즉, 두 번째 인자를 통해 소수점 몇 째 자리까지 반올림 할 것인지를 지정할 수 있다. 두 번째 인자를 생략하면 첫 번째 인자로 받은 숫자에서 가장 가까운 정수를 리턴하게 된다.
예를 들어보자.
import math
print(round(1.535, 2))
print(round(2.5234, 2))
print(round(-1.5453, 2))
print(round(-2.5234, 2))
# 1.53
# 2.52
# -1.55
# -2.52
두 번째 인자로 2를 줬다는 것은 소수점 두번째 자리까지 반올림을 하겠다는 의미다. 따라서 결과로 소수점 두 번째 자리를 갖는 숫자가 리턴되었다. 이 때에도 오사오입이 적용되어 1.535를 소수점 두번째 자리까지 반올림을 했더니 1.53이 리턴되었다.
부동소수 반올림
반올림과 관련해서 오사오입 동작이 뭔지 알아봤다. 하지만 프로그래밍 언어에서 부동소수점 숫자는 부정확하다. 다음 예를 보자.
import math
num1 = 1.3 + 2.3 - 0.1
num2 = 3.5
print(round(num1))
print(round(num2))
1.3 + 2.3 - 0.1 을 계산하면 3.5다. 결국 num1과 num2는 같은 값을 가져야한다. 따라서 round() 함수에 태워도 동일한 값이 나와야 한다. 하지만 그렇지 않다.
# 3
# 4
위 값은 3이 리턴되고, 아래 값은 4가 리턴된다. num1과 num2를 출력해보면
import math
num1 = 1.3 + 2.3 - 0.1
num2 = 3.5
print(num1)
print(num2)
# 3.4999999999999996
# 3.5
실제로 같은 값이 아니다. 파이썬을 비롯한 다양한 프로그래밍 언어에서는 부동소수점을 정확하게 표현하기 힘들다는 문제점이 있다. 이런 점을 잘 이해하고 사용해야 과학 수식에서 사용하는 등 정확한 값을 필요로하는 곳에서 문제가 발생하지 않는다.
댓글