연산자 우선순위의 중요성

죠랭이·2021년 3월 6일
0

알고리즘

목록 보기
3/3
post-thumbnail

오늘은 연산자 우선순위의 중요성에 대해 이야기해보려고 한다. 이항계수 관련 문제를 접하면서 백준에서 이항계수 문제들을 풀던 중 다음의 재미난 문제를 발견하였다.
3651_백준

처음에는 단순히 이항계수 DP 해결방식으로 접근하였으나 O(N^2) 시간복잡도로는 시간초과 결과가 나오기에 어떻게 해결해야할지 고민하던 중 다음 블로그의 도움을 받았다.
3651백준문제풀이_해설

문제를 맞은 후 여러 pass 코드들을 보며 좀 더 간결한 로직의 코드를 찾아 이해하고 이를 토대로 문제를 다시 풀어보았는데 결과가 다음과 같았다.

정말 이해가 가질 않았다. 내 머리속으로 계산한 바로는 전혀 틀릴만한게 없었기 때문이다. 혹시나 싶어 참고한 코드를 읽어 내려가는데 도저히 어디서 틀렸는지 이해가 되질 않았다. 여러 추측들을 검증해가는 과정에서 하나의 의구심이 들기 시작하였다.

long long nCk(long long n, int k) {
    double res = n - k + 1;
    for(int i = 2; i <= k; i++) {
    	res *= (n - k + i) / i; // 처음 작성한 코드
     //   res = res * (n - k + i) / i;
    }
    if(res > pow(10, 16)) return (long long) pow(10, 16);
    return (long long) res;
}

이항계수를 구하는 함수에서 for문 안의 연산자를 다르게 써줬는데 알아보니 연산자 우선순위가 , / 가 먼저이고 그 다음이 = 연산자라고 한다.(C언어 연산자 순위) 그러다보니 해당 구문에서 / 가 먼저 시행되어 버리기에 연산과정에서 소수점 발생으로 전혀 예상치 못한 계산값을 리턴할 수 있는 버그가 있었다. 이 부분을 아래 주석 처리한 부분처럼 * 연산자로 바꿔주니 무리없이 패스할 수 있었다.

이렇듯 단순 알고리즘 문제해결뿐만 아니라 프로젝트 상에서도 연산자 우선순위로 인하여 예상치 못한 값이 발생할 수 있기에 / 연산에서는 특히나 주의를 기울여야함을 배울 수 있었다...

profile
슈퍼 개발자를 목표로 하는 주니어

0개의 댓글