본문 바로가기
Study

프로그래밍 언어에서의 나눗셈과 나머지 연산 차이

by 개발새-발 2025. 5. 11.
반응형

우리가 수학에서 정수 나눗셈나머지(modular) 연산을 다룰 때는, 나머지가 0 이상인 정수이다. 하지만 프로그래밍 언어에서는 이러한 연산이 언어마다 다르게 정의되며, 그 차이는 특히 음수 연산에서 두드러진다. 이로 인해 프로그램이 의도와 다르게 동작할 수 있으므로, 정확한 이해가 필요하다.

1. 사례: C++ vs Python

C++

int a = -5 / 2;  // 결과: -2
int b = -5 % 2;  // 결과: -1

Python

a = -5 // 2  # 결과: -3
b = -5 % 2   # 결과: 1

둘 다 -5 ÷ 2를 계산하는 코드지만, 결과는 다르다.


2. 핵심 차이: 몫 연산의 방향성과 나머지의 부호

나눗셈을 수행할 때 소수점 이하의 값을 어떻게 처리하느냐에 따라 이러한 차이가 발생한다.

C++: 0을 기준으로 내림(truncate toward zero)

  • 나눗셈 /: 소수점 이하는 0 방향으로 버림
    -5 / 2 = -2
  • 나머지 %: a = q * d + r 관계를 만족시키되, 나머지 r은 피제수(a)와 같은 부호
    -5 = (-2) * 2 + (-1)

Python: 음의 무한대로 내림(floor division)

  • 나눗셈 //: 결과를 항상 아래 방향(−∞) 으로 내림
    -5 // 2 = -3
  • 나머지 %: 제수와 같은 부호를 가지며, 항상 0 ≤ r < |d|를 만족
    -5 = (-3) * 2 + 1

3. 나머지 정리

정수 나눗셈은 다음의 기본식으로 표현된다:

a = q * d + r

여기서

  • a: 피제수
  • d: 제수
  • q: 몫
  • r: 나머지

그리고 나머지는 아래 조건을 만족해야 한다:

0 ≤ r < |d|

즉, Python의 정수 나눗셈과 모듈러 연산은 수학적인 floor 기반 나머지 정리를 충실히 따르지만, C++은 몫을 0 방향으로 자르고 나머지를 피제수의 부호로 맞추는 방식으로 구현되어 있다.


4. 왜 이런 차이가 생겼을까?

C/C++/Java의 이유:

  • 성능 중심의 설계
  • 하드웨어의 idiv 명령은 몫을 0 방향으로 자르는 방식을 따름
  • 따라서 q = trunc(a / b) 구현이 간단함

Python의 이유:

  • 수학적 일관성을 중시
  • 나머지가 항상 제수의 부호를 따르며, 0 ≤ r < |d|를 만족
  • 반복문, 배열 인덱싱 등에서 더 직관적인 동작을 제공

예:

for i in range(-3, 4):
    print(i % 3, end=' ')

출력 결과:

0 1 2 0 1 2 0

5. 모듈러 연산(mod)과의 관계

mod 연산은 수학적으로 다음과 같이 정의된다:

a mod d = a - d * floor(a / d)

이 정의는 Python의 % 연산과 일치한다.

C++의 %는 이 정의와 다르게 동작하므로, Python과 동일한 결과를 얻기 위해선 다음과 같이 보정할 수 있다:

int mod(int a, int d) {
    int r = a % d;
    return r < 0 ? r + abs(d) : r;
}

✅ 요약

항목 C++ / Java Python
나눗셈 0 기준 내림 (truncate) 아래 방향 내림 (floor)
나머지 피제수 a와 같은 부호 제수 d와 같은 부호
a = q*d + r 만족 여부
mod 수학적 의미와 일치
반응형

'Study' 카테고리의 다른 글

Julian Day Number (율리우스 적일)  (0) 2025.05.08

댓글