Codefights.com에서 Arcade - Python 을 풀다가 상당히 재미있는 버그를 하나 알게 되어 작성한다.


1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
 
int division(int x, int y)
{
    return x / y;
}
int main()
{
    std::clog << division(15-4<< std::endl;
    return 0;
}
cs

 C에서 이렇게 int끼리의 나눗셈의 결과가 나머지가 존재할 경우, '/' 연산자 특성상 나머지를 버리고 몫만을 리턴하기 때문에 결과 값은 -3이 된다. 소숫점으로 나타내면 -3.xx~ 로 나타나겠지만 int 형으로 형변환하면서 -3이 되는 것이다. 

( C에서는 두 오퍼랜드 모두 Integer형일 경우 Integer를 반환하고, 하나라도 Float일 경우 Float형으로 소숫점을 붙여 반환한다. 이를 Classic Division이라고 한다. )


1
2
3
4
def division(x, y):
    return x / y
 
print division(15-4)
cs

 하지만 같은 역할을 할 법한 코드를 Python 2에서 작성하여 쓸 경우, 예상과는 달리 -4가 리턴된다. 

 이는 흔히 Floor Division 이라고 일컫는 정수 나눗셈 방법인데, 두 오퍼랜드가 모두 정수이고 나누어져서 나온 결과가 정수가 아니라면 항상 나온 값보다 작은 정수를 리턴하는 방식이다. 예를 들어, 5/3 의 경우 1.xx 로 1보다는 크고 2보다는 작은 값이 나오므로 1이 리턴된다. 따라서 위의 예시인 15/-4 를 할 경우 -3과 -4 사이의 값이므로 더 작은 값인 -4가 리턴되는 것이다. 이 방식이 문제가 되는 이유는, 흔히 참이라고 생각하는 연산이 거짓이 된다는 점에 있다.

 예를 들면, 정수 x와 y에 대해서, (x/-y) == -(x/y) 는 당연히 참이 되어야 하지만, 실제 위의 예시를 들어 보면 (15/-4) 는 -4가 되고 -(15/4) 는 -3이 되므로 거짓이 되어버린다. 

 이 문제는 Python 3 버전에서는 고쳐졌다고 한다. Python 3에서는 정수를 정수로 나누어도 Float을 반환해버리는 True Division을 사용하기 때문에 애초부터 저런 문제가 발생하지 않으며, Floor Division을 사용하고 싶을 때에는 15//-4 처럼 '//' 연산자를 사용하면 된다.

블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

댓글을 달아 주세요