Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++에서 곱셈 시 64비트 정수 오버플로 확인하는 방법

두 수 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)를 활용하는 방법도 있습니다.