포스트

프로그래머스 12937 - 짝수와 홀수 (Lv.1)

핵심 접근 — 음수까지 안전한 판정은 % 2 == 1이 아니라 % 2 == 0

프로그래머스 12937 - 짝수와 홀수 (Lv.1)

출처: https://school.programmers.co.kr/learn/courses/30/lessons/12937

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 프로그래머스 12937 - 짝수와 홀수 (Lv.1)
// https://school.programmers.co.kr/learn/courses/30/lessons/12937

// 문제 설명
// 정수 num이 짝수면 "Even", 홀수면 "Odd"를 반환하라.

// 제약 조건
// num은 int 범위의 정수 (음수 포함)
// 0은 짝수로 취급한다

// Example
// Input : num = 3
// Output: "Odd"
//
// Input : num = 4
// Output: "Even"

// 접근 — 비교 대상을 1이 아니라 0으로 잡는다
// 로직은 한 줄이지만 제약에 "int 범위"가 붙은 순간 음수가 입력에 포함된다.
// C++는 정수 나눗셈을 0 방향으로 절단하므로 나머지의 부호가 피제수를 따라간다.
//   -3 / 2 == -1,  -3 % 2 == -1     (파이썬의 -3 % 2 == 1과 다르다)
// 따라서 홀수 판정을 num % 2 == 1로 쓰면 음의 홀수가 전부 "Even"으로 새어 나간다.
// 나머지가 0이냐 아니냐로 물으면 부호와 무관하게 항상 맞는다.
//   짝수 -> 나머지 0,  홀수 -> 나머지 +1 또는 -1 (둘 다 "0이 아님")
// num & 1도 2의 보수 표현 덕에 음수까지 정확하지만, abs(num)으로 부호를 지우려는 시도는
// INT_MIN에서 오버플로(정의되지 않은 동작)라 쓰면 안 된다.
// 시간 O(1), 공간 O(1)

#include <string>

using namespace std;

string solution(int num) {
    return num % 2 == 0 ? "Even" : "Odd";   // 0과 비교 — 음수에서 나머지가 -1이라 == 1은 틀린다
}

정리

  • % 2 == 1은 음수에서 깨진다. C++는 나눗셈을 0 방향으로 절단(truncation)해 나머지의 부호를 피제수에 맞추므로 -3 % 2-1이다. 파이썬은 바닥 나눗셈이라 1이 나오고, 이 차이를 그대로 옮기면 언어를 바꿀 때 조용히 틀린다. 판정은 항상 == 0 / != 0으로 걸어 두면 부호에 독립적이다.
  • num & 1도 안전하다. 2의 보수 표현에서 최하위 비트는 부호와 무관하게 홀짝을 그대로 담기 때문이다(-3...11111101로 LSB가 1). 다만 &는 우선순위가 ==보다 낮아 if (num & 1 == 0)처럼 쓰면 num & (1 == 0)으로 파싱된다 — 괄호가 필요하다.
  • abs(num)으로 부호를 지우려는 우회는 함정이다. int 범위에는 INT_MIN(-2,147,483,648)이 있고 그 절댓값은 int로 표현할 수 없어 abs(INT_MIN)은 정의되지 않은 동작이다. “제약에 int 범위가 적혀 있다”는 건 INT_MIN·INT_MAX가 테스트에 들어온다는 신호로 읽는 게 맞다.
  • 0을 어느 쪽으로 셀지 문제가 명시한다. 여기서는 짝수이고, 0 % 2 == 0이라 별도 분기 없이 자연히 맞아떨어진다. 명시가 없다면 되묻거나 경계 테스트를 따로 만들어야 하는 지점.
  • 반환값이 두 가지뿐이므로 if/else 대신 삼항 연산자 한 줄로 정리했다. 문자열 리터럴이 std::string으로 암시 변환되므로 반환형만 맞으면 그대로 동작한다.
  • 검증: 예제 2개(“Odd”, “Even”)와 경계 케이스 5개 — 0(“Even”), -3(“Odd”), -4(“Even”), INT_MIN(“Even”), INT_MAX(“Odd”) 전부 통과 (MSVC /std:c++17 /utf-8 컴파일·실행). -3% 2 == 1 구현이었다면 여기서 깨졌을 케이스다.

핵심 요약 — C++의 나머지는 부호를 피제수에서 물려받아 -3 % 2 == -1이다. 홀짝 판정을 == 1이 아니라 == 0으로 걸어야 음수까지 맞고, abs로 부호를 지우는 우회는 INT_MIN에서 정의되지 않은 동작이 된다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.