[TIL] (230819) 제한사항의 범위와 변수의 범위가 애매하다면 꼭 log를 찍어보자!!

Noh Jihyeon·2023년 8월 19일
0

TIL

목록 보기
6/49
post-thumbnail

오늘도 프로그래머스 문제를 풀다가 이상한걸 발견했다.
분명 나는 문제가 원하는 조건대로 코딩을 진행했고 또 제출까지 완료됐는데 같은 조건이라고 생각했던 코드를 조금 바꾸니까 답이 나오질 않는다.
이게 어떻게 된걸까?




🔸문제점

프로그래머스 - 콜라츠 추측

https://school.programmers.co.kr/learn/courses/30/lessons/12943

나는 이 문제를 보고 아래와 같이 판단했다

1) 짝수 판별 후   n * 2
2) 홀수 판별 후   n * 3 + 1

* 홀,짝 판별 = if문

그리고 이렇게 코딩했다.

class Solution {
    public int solution(int num) {
        int answer = 0;

        while (num !=1) {
            if(answer >= 500) {
                return -1;

            } 
            if(num % 2 == 0) {num /= 2;}
            else if (num % 2 == 1) {
                num = num * 3 + 1;
            }
             answer++;
        }
        return answer;
    }
}

=> 정상제출 완료


그런데 이렇게 제출하고 보니 if문을 삼항연산자로 바꾸고 싶었다.

그래서 if문을

num = (num % 2 == 0)? num/= 2: num * 3 + 1;

이렇게 수정했는데 검증숫자 626331에서 -1이 아닌 488로 종료되는 문제가 생겼다.





2로 나눈 나머지가 0이라면 짝수, 아니라면 뭐가 다른걸까..?



🔸시도해본 것들


먼저 기존 코드로는 시도횟수 500번 초과로 -1이 나왔으나 삼항연산자로는 488번으로 출력되는것에 집중해봤다.

분명 같은 식을 진행하는데 몇번째의 어떤 값에서 달라지는건지 전부 출력해봤다.





104번째 반복부터 음수가 나오는걸로 보아 오버플로우가 발생한 것 같다.
하지만 같은 오버플로우여도 값이 다른 이유가 뭘까?

=> 정답은 반환값 -1의 처리여부였다.

	// (1)
	if(num % 2 == 0) {num /= 2;}
	else if (num % 2 == 1) {num = num * 3 + 1;}
	answer++;
    
/////////////////////////////////////

	// (2)
    num = (num % 2 == 0)? num/= 2: num * 3 + 1;

             


1의 경우 105번째 시도부터 계산한 결과가 -1로 나온다.
-1은 if, else if 그 어떤것도 만족하지 않기 때문에 같은 값이 계속 나오면서 계산이 진행되지 않고 이렇게 최대횟수 500번을 넘겨셔 -1값이 반환됐던 것이다.

if-else if문은 오류가 발생했으나 그 오류덕분에 정답처리로 된 것이다.

이런 황당한 일이;;;



이론상으로는 이해했지만 혹시 모르니까 앞선 경우와 마찬가지로 값을 직접 찍어보자!!



문제가 발생했던 104번째의 값이 약 32억으로
int의 범위 (-21억~ +21억)을 벗어나서 오버플로우가 발생한게 맞았다.

이렇게 눈으로 직접 비교하니 확실하게 알겠다!!




🔸해결




class Solution {
    public int solution(int num) {
        int answer=0;
        Long num2 = (long)num;

        while (num2 !=1) {
            if(answer >= 500) {
                return -1;

            } 
            num2 = (num2 % 2 == 0)? num2/= 2: num2 * 3 + 1;
            answer++;
        }
        return answer;
    }
}

int형이 아닌 Long타입으로 변경 후 계산하기



🔸알게 된 점

개발자는 만일의 만일의 만일까지 발생할 수 있는 모든 예외사하을 체크하고 대응해야 한다.
만약 내가 단순히 문제를 통과한것으로 그냥 넘어갔다면 어부지리로 걸린 결과라는걸 생각하지 못했을 것이다.
문제에서 제한조건이 괜히 주어지는게 아니다.
무조건 Long타입으로 변환하여 데이터를 많이 차지하는것은 좋지 않다.
어떤 상황일때 변환이 필요한지 판단하고 적재적소에 형변환을 진행하는게 실력이라고 생각한다.

이번일을 계기로 나는 int형으로 주어진 문제와 제한조건을 살펴본 후 간단한 계산식이라면 경우의 수의 최대값을 먼저 체크하는 습관이 생길것 같다.
또한 식이 복잡하여 직접 계산이 어려운 경우라면 Long타입과 int타입 두가지로 계산 후 결과값이 같은지 비교검증을 진행할 예정이다.

profile
꼭꼭 씹어서 소화시키는 맛있는 코딩

0개의 댓글