본문으로 건너뛰기
김신건의 로그

임의 정밀도 / 큰 수 산술 (Arbitrary Precision)

· 수정 · 📖 약 2분 · 715자/단어 #algorithm #math #arbitrary-precision #big-integer #arithmetic
arbitrary precision, big integer, 임의 정밀도, 큰 수 산술, arbitrary-precision

정의

임의 정밀도 (Arbitrary Precision) 또는 큰 수 산술 (Big Integer / Bignum) 은 고정된 바이트 한계(32-bit, 64-bit) 없이 메모리가 허용하는 한 임의로 큰 정수를 표현하고 연산하는 기법. 배열에 자릿수를 저장하고 학교 교과서 방식 (O(n^2)) 또는 Karatsuba (O(n^1.585)), FFT/NTT (O(n log n)) 곱셈으로 구현.

문제 상황과 동기

C long long (64-bit, 약 ±9.22×10^18) 으로 표현 불가능한 수를 다룬다. 10000자리 소수 곱셈, 암호학 (RSA 2048-bit key), 조합론 (nCr, n≤100000) 등.

  • naive: built-in 64-bit overflow. 해결 불가.
  • string/vector 기반: Base 10 또는 Base 10^9 표현. 덧셈/뺄셈 O(n), 곱셈 O(n^2) (schoolbook) / O(n^1.585) (Karatsuba) / O(n log n) (FFT).

핵심 통찰: 큰 수를 작은 단위(자릿수)로 분할. 올림(carry)을 순차 전파.

시각화

핵심 아이디어

숫자를 자릿수 배열로 표현. a[0] = 일의 자리. 덧셈은 각 자리별 덧셈 + 올림 전파.

10^N base 표현 (각 원소가 0~9):
  n = a_0 + a_1·10 + a_2·10^2 + ... + a_{k-1}·10^{k-1}

덧셈:
  for i = 0..k-1:
    sum = a_i + b_i + carry
    result_i = sum % 10
    carry = sum / 10

곱셈 (schoolbook):
  for i = 0..ka-1:
    for j = 0..kb-1:
      result[i+j] += a_i * b_j
  // 올림 정리

구현

// String 기반 큰 수 더하기 (Base 10)
#include <bits/stdc++.h>
using namespace std;

string add(string a, string b) {
  if (a.size() < b.size()) swap(a, b);
  int carry = 0;
  for (int i = a.size() - 1, j = b.size() - 1; i >= 0; i--, j--) {
      int sum = (a[i] - '0') + (j >= 0 ? b[j] - '0' : 0) + carry;
      a[i] = (sum % 10) + '0';
      carry = sum / 10;
  }
  if (carry) a = char(carry + '0') + a;
  return a;
}

int main() {
  string a, b; cin >> a >> b;
  cout << add(a, b);
  return 0;
}
stdin
1234 5678
결과
6912
7006652

복잡도

항목
덧셈/뺄셈 (시간)O(n)
곱셈 (schoolbook)O(n^2)
곱셈 (Karatsuba)O(n^{log_2 3}) ≈ O(n^1.585)
곱셈 (FFT/NTT)O(n log n)
공간O(n)

변형 / 활용

Karatsuba 곱셈

큰 수를 반으로 분할: a = a1·B^m + a0, b = b1·B^m + b0. 곱셈 3회로 축소 (n^2 -> n^1.585).

z2 = a1·b1
z0 = a0·b0
z1 = (a1+a0)·(b1+b0) - z2 - z0
결과 = z2·B^{2m} + z1·B^m + z0

FFT/NTT 곱셈

convolution 으로 변환하여 O(n log n). 수십만 자리 이상에서 실용적. FFT/NTT 문서 참조.

Base 변환

10진 입출력에 유리한 Base 10 vs 연산 효율의 Base 10^9. 내부 Base 2^64 (GMP 스타일).

함정

1. 음수 처리

뺄셈에서 부호 결정. sign 플래그 분리 또는 보수 표현.

2. leading zero

연산 후 앞쪽 불필요한 0 제거. 결과가 0이면 하나의 0 유지.

3. 캐리 전파 지연

덧셈/곱셈 후 올림이 연쇄 전파될 수 있음. 한 번의 정리 패스로 해결.

4. FFT 반올림 오차

복소수 FFT 는 부동소수점 오차 발생. NTT (정수 mod prime) 로 대체.

BOJ 연습 문제

번호제목정답률링크
BOJ 10757큰 수 A+B51.3%kokoa-lab
BOJ 2338긴자리 계산49.9%kokoa-lab
BOJ 1271엄청난 부자235.6%kokoa-lab
BOJ 2407조합42.6%kokoa-lab

참고

이 글의 용어 (3개)
분할 정복을 이용한 거듭제곱 (Exponentiation by Squaring)algorithm
정의 분할 정복을 이용한 거듭제곱 (Exponentiation by Squaring) 은 을 O(log n) 시간에 계산하는 분할 정복 알고리즘. 같은 모듈러 연산에서 특히 필수…
사칙연산 (Arithmetic Operations)algorithm
정의 사칙연산 (Arithmetic Operations) 은 덧셈, 뺄셈, 곱셈, 나눗셈의 정확한 구현을 다루는 PS 태그. 큰 수 표현 (large integer), 오버플로우…
FFT, NTTalgorithm
정의 FFT (Fast Fourier Transform, 고속 푸리에 변환) 은 길이 인 수열의 이산 푸리에 변환 (DFT) 을 O(n log n) 에 계산하는 분할정복 알고리즘…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기