두 수 A와 B를 곱한 결과를 구하고자 할 때, 그 결과값이 64비트 정수(long long)의 표현 범위를 초과하는지, 즉 오버플로(overflow)가 발생하는지 반드시 확인해야 합니다.
예를 들어 100 × 200 = 20,000은 64비트 정수 범위 안에 있으므로 문제가 없지만, 10,000,000,000 × (-10,000,000,000)처럼 매우 큰 수를 곱하면 결과가 범위를 벗어나 오버플로가 발생합니다.
오버플로 확인 절차
곱셈 결과의 오버플로 여부는 다음 단계를 통해 판별할 수 있습니다.
두 수 중 하나라도 0이면 → 곱셈 결과는 항상 0이므로 오버플로가 발생하지 않습니다.
곱셈 결과를 한쪽 수로 나눈 몫이 다른 한쪽 수와 같으면 → 결과가 정상적으로 표현된 것이므로 오버플로가 발생하지 않습니다.
그 외의 경우 → 곱셈 과정에서 값이 잘려나갔다는 의미이므로 오버플로가 발생한 것입니다.
이 방식은 실제 곱셈을 수행한 뒤 역으로 나눗셈으로 검증하기 때문에, 별도의 큰 자료형이나 복잡한 조건 분기 없이 간단하게 오버플로를 감지할 수 있다는 장점이 있습니다. 또한 먼저 0 여부를 확인하므로 0으로 나누는 오류(divide-by-zero)도 자연스럽게 방지됩니다.
예제 코드
#include <iostream>
#include <cmath>
using namespace std;
bool isMulOverflow(long long A, long long B) {
// 하나라도 0이면 오버플로 없음
if (A == 0 || B == 0)
return false;
long long result = A * B;
// 역나눗셈으로 원래 값과 일치하는지 검증
if (A == result / B)
return false; // 오버플로 없음
else
return true; // 오버플로 발생
}
int main() {
long long a = 10000000000, b = -10000000000;
if (isMulOverflow(a, b)) {
cout << "It will overflow";
} else {
cout << "It will not overflow";
}
}실행 결과
It will overflow
10,000,000,000 × (-10,000,000,000)의 실제 결과는 -100,000,000,000,000,000,000으로 64비트 부호 있는 정수의 최댓값(약 9.22 × 10¹⁸)을 훨씬 초과합니다. 따라서 위 코드는 오버플로가 발생했다고 올바르게 판별합니다.
참고 사항
C++에서 부호 있는 정수의 오버플로는 정의되지 않은 동작(undefined behavior)입니다. 즉, 오버플로가 발생한 상태에서 프로그램이 계속 실행되면 예측 불가능한 결과가 나올 수 있습니다. 따라서 실무에서는 곱셈 전에 피연산자의 크기를 미리 검사하거나, 위와 같은 검증 함수를 활용해 안전하게 처리하는 것이 좋습니다. C++17 이상에서는 <numeric> 헤더의 std::multiplies와 함께 검사 로직을 사용하거나, 컴파일러 내장 함수(예: GCC/Clang의 __builtin_mul_overflow)를 활용하는 방법도 있습니다.