나눗셈 이야기

파이썬 강의를 할 기회가 있었습니다. 아무런 배경 없이 기초부터 접근했는데, 정리하다 보니 파이썬의 나눗셈이 초보자에게는 그리 만만하지 않다는 것을 발견하게 되었습니다. 그래서 짧은 글을 쓰게 되었는데, 이 곳에도 올려둡니다. 기초적인 내용이라 너무 고급스러운 글을 기대하시는 분들에게는 적당하지 않습니다.

수학이 문제야

우리가 그냥 나눗셈이라고 부르는 계산법은 사실 두 가지 입니다. 한가지는 시중에서 팔리고 있는 계산기가 잘하는 나눗셈입니다. 5 를 2로 나누면 2.5 가 나오지요. 저는 실수 나눗셈이라고 부릅니다. 반면에 소수점이라는 것을 들어보지도 못했던 어린 시절을 잘 더듬어 보면, 나눗셈과 함께 등장했던 몫과 나머지가 기억나실 겁니다. 5 를 2로 나누면 몫이 2이고 나머지가 1이라고 하지요. 저는 정수 나눗셈이라고 부릅니다. 많은 언어에서 '/' 기호는 실수 나눗셈과 정수 나눗셈 모두에 사용됩니다. 규칙은 이렇습니다.

'/' 기호 양쪽에 있는 숫자가 모두 정수면 결과는 정수 나눗셈의 몫이고, 그렇지 않으면 실수 나눗셈을 취한다.

그러니 2.5 를 얻고 싶으면 5/2 라고 쓰는 대신에 5.0/2 라고 쓰라고 합니다. 혼란스럽다고해서 학생을 탓할 문제가 아닙니다. 사실 파이썬 제작자들은 이 문제를 꽤 심각하게 받아들이고 있습니다. 그래서 파이썬 에는 '//' 라는 정수 나눗셈 전용 기호가 하나 더 준비되어 있습니다. 5//2 라고 쓰면 2가 나오는 것은 마찬가지입니다. 하지만 5.0//2 라고 써도 2.5 대신 2.0 이 나온다는 뜻입니다. 나머지를 위한 기호 '%' 가 정수 나눗셈 전용임을 상기한다면, 적어도 정수 나눗셈을 위해서는 완벽한 세트가 구비되었습니다. 내친 김에 정수 나눗셈의 '정수'를 '몫' 에만 적용시키고 다른 모든 부분에는 실수가 나올 수 있게 풀어버렸습니다. 5.5//2.2 라는 표현이 가능하고 그 결과가 2.0 이라는 뜻입니다. 당연히 5.5%2.2 는 1.1 이 되겠지요? 정수 나눗셈은 전용 세트가 구비되었는데, 실수 나눗셈 전용 기호는 없고 혼란의 주범인 '/' 는 상황에 따라 이렇게도 쓰였다가 저렇게도 쓰였다가 한다는 뜻이군요. 파이썬 2.X 에서는 호환성 문제 때문에 어쩔 수 없지만, 3.X 버전에서는 에서는 '/' 기호를 실수 나눗셈 전용으로 바꿨습니다. 그러니 지금이라도 정수 나눗셈을 원하실 때는 '//' 기호를 사용하시는 버릇을 들여놓으시면 좋습니다.

음수는 더 문제야

정수 나눗셈을 음수에 대해 적용하려고 하면 혼란은 한층 더합니다. 이 경우는 아는 것이 병이라고 C, C++, Java 등의 언어에 익숙하신 분들은 파이썬과는 다른 종류의 정수 나눗셈을 하고 있습니다. 이 세 언어를 합쳐 C부족 이라고 부릅시다. 아주 예전의 C 언어는 음수가 포함된 정수 나눗셈에 대해 "컴파일러 맘대로 하세요" 였지만 요즘은 “0을 향해 모여" 로 정리되었습니다. C++ 은 당연하고 Java 도 마찬가지 입니다. 반면 파이썬은 "무조건 내려" 입니다. 무슨 소리인고 하니 5/(-2) 를 계산하려면 일단 실수 나눗셈을 해서 -2.5 를 구합니다. 이 숫자를 C 부족은 0과 더 가까운 -2 로 정리하고, 파이썬은 더 작은 숫자인 -3으로 결정한다는 뜻입니다. 이 규칙을 잘 기억할 수 있도록 도우려고, 제가 쓰는 "정수 나눗셈" 이라는 용어 보다는 Floor Division 이라는 용어를 사용합니다. 그러면 "실수 나눗셈"은? 이 역시 저와는 다른 True Division 이라는 용어를 사용합니다. 그러면 나머지는 어떻게 구할까요? 여기에 대해서는 모든 언어가 합의할 수 있는 방법이 있습니다. 다음 식을 보세요.

x % y == x - (x // y) * y

혹시 수학시간에 본 듯한 기억이 나시나요? 규칙에 대해 합의할 수 있다는 것이지 결과가 같다는 뜻은 아닙니다. 몫이 바뀌니 나머지도 바뀔 수밖에 없겠지요. 조금 더 파보면 0이 아닌 x % y 의 부호는 파이썬의 경우 y 와 같고, C부족의 경우 x 와 같음을 증명할 수도 있습니다. 하지만 이 그럴듯해 보이는 규칙을 실수에 적용할 때는 주의하셔야 합니다. 첫째로 '==' 기호는 “거의 같다”로 해석하셔야 하고, 둘째로 라운드에러 때문에 쓸모 없는 결과가 나올 수도 있습니다. 예를 들어 파이썬 2.7에서 6.6//2.2 는 3.0 이 아니라 2.0 이 나옵니다.

아빠가 문제야

예전에는 나눗셈이 엄청 쉬웠는데, 요즘은 나머지가 있어서 어렵다는 딸아이가 늘 끝에 정리해주는 결론입니다.