사실 이 문제는 풀면서도 포스팅할 생각을 하지 않았던 문제입니다.
하지만 다른 분들의 풀이를 보고, 다른 방식으로 접근했을 때 발생한 에러와 그 이유를 공유하고 싶어서 포스팅하게 되었습니다.
📖 문제
정수 num이 짝수일 경우 "Even"을 반환하고 홀수인 경우 "Odd"를 반환하는 함수, solution을 완성해 주세요.
⛔ 제한 조건
- num은 int 범위의 정수입니다.
- 0은 짝수입니다.
💻 입출력 예
| num | return |
| 3 | "Odd" |
| 4 | "Even" |
짝수의 특성인 2로 나눴을 때 나머지가 0인 점을 이용하여 코드를 구현했습니다.
class Solution {
public String solution(int num) {
String answer = "";
if ((num % 2) == 0) {
answer = "Even";
} else {
answer = "Odd";
}
return answer;
}
}
하지만 다른 분들의 풀이를 보니, if-else문에서 홀수를 먼저 처리하거나 if문 두 개로 독립적으로 홀수를 판별하는 경우 제대로 실행되지 않는 경우가 있다고 합니다.
class Solution {
public String solution(int num) {
String answer = "";
if ((num % 2) == 1) {
answer = "Odd";
} else {
answer = "Even";
}
return answer;
}
}

제한 조건을 보면 num은 int 범위의 정수로, 음의 정수일 경우도 고려해야 한다는 것을 알 수 있습니다.
음의 정수일 경우 2로 나누면, 짝수일 때는 나머지 값이 0이고 홀수일 때는 나머지 값이 1일 거라 유추해 볼 수 있습니다.
public class Test {
public static void main(String[] args) {
// 음의 정수 나눗셈 (1) - 짝수
int num = -12;
num %= 2;
System.out.println(num); // (-12) % 2
// 음의 정수 나눗셈 (2) - 홀수
num = -11;
num %= 2;
System.out.println(num); // (-11) % 2
}
}

하지만 결과는 -1 임을 확인할 수 있습니다.
기존과 달라진 점은 나눗셈 연산의 피연산자가 음수인 것으로, 음수인 피연산자의 나눗셈 연산 처리 과정에서, 어떠한 방식으로 결과가 달라졌다는 것을 알 수 있습니다.
음수의 나눗셈 연산
음수 연산에 대해서 다음의 순서로 접근해 보겠습니다.
음의 정수 표현법 → 음의 정수 나눗셈
1. 음의 정수 표현법
• 정수 표현
컴퓨터는 N개의 비트를 이용해 2^N개의 정수 표현할 수 있습니다. 하지만 이 음수와 양수 모두 표현해야 하기 때문에, 이를 위한 규칙이 필요합니다.
• 보수
보수란, '두 수의 합이 특정 진법의 밑수(N)가 되게 하는 수'를 말합니다.
예를 들어 10진수 4의 10의 보수는 6이고 (4 + ? = 10), 10진수 2의 10의 보수는 8 (2 + ? = 10)입니다.
이를 2진수에서도 사용하며, 이를 이용하여 음수를 표현하고 덧셈으로 뺄셈을 구현합니다.
컴퓨터 내부에서 사칙연산은 덧셈 연산을 하는 가산기(Adder)만 이용하기 때문에, 뺄셈은 덧셈으로 변환하여 계산해야 합니다.
즉, 컴퓨터 내부에서는 A - B를 계산하려면 B의 보수(-B)를 구한 후 A + (-B)로 계산하는 것입니다.
1) Signed Magnitude
- MSB에 부호 표현
- 보통은 0은 (+), 1은 (-) 를 의미합니다.
2) 1의 보수 (1's Complement)
총 N개의 비트로 정수를 표현할 때, 모든 N비트가 1로 이루어진 수 (2^N - 1 = 111... 11(2)) 에서 표현하고 싶은 음수의 절댓값을 뺀 수가 바로 1의 보수 방법으로 표현한 음수가 됩니다.
3) 2의 보수 (2's Complement)
총 N개의 비트로 정수를 표현할 때, 2^N = 1000... 0(2)에서 표현하고 싶은 음수의 절댓값을 뺀 수가 바로 2의 보수 방법으로 표현한 음수가 됩니다.
2. 음수의 나눗셈 처리
- 언어마다 나눗셈 연산 처리 과정 중, 몫을 절삭하는 방식이 다릅니다.
- Java 나 C 의 관점
- 나머지 값의 부호가 (+)와 (-), 모두 가능합니다.
첫 번째 피연산자의 부호만을 따릅니다.- 피연산자들을 모두 양수로 변환합니다.
- 양수로 변환한 값들을 이용하여 연산합니다.
- 연산한 값에 첫 번째 피연산자의 부호를 붙입니다.
- 몫을 0에 가까운 값으로 절삭합니다.
즉, 나눗셈 결과의 소수 부분을 버리고, 소수점 아래를 버린 값을 반환합니다.
- Python
- 나머지 값의 부호는 양수만 가능합니다.
- 나눗셈의 몫을 더 작은 정수로 절삭하는 방식으로 처리합니다.
즉, 내림(floor)을 적용합니다.
+) 전공 때 배운 비트연산 되짚기!
🔎 Shift를 이용한 곱셈/나눗셈 연산
- << : 피연산자의 비트열을 왼쪽으로 이동시키고, 비트열 이동에 의한 빈 공간은 0으로 채워줍니다.
- >> : 피연산자의 비트열을 오른쪽으로 이동시키고, 비트열 이동에 의한 빈 공간을 음수일 때는 1, 양수일 때는 0으로 채워줍니다.
- >>> : 피연산자의 비트열을 오른쪽으로 이동시키고, 비트열 이동에 의한 빈 공간은 0으로 채웁니다.


