guest@itl:~/home/utilities$
templates/big-integer.cpp
compilable
$cat templates/big-integer

Big Integer

Non-negative arbitrary-precision integer with addition, subtraction, multiplication, division, and modulo.

[Utilities]|
Jul 9, 2026
|explanatory_notes.md|
#bigint#arbitrary-precision#big-integer#math
Log in to track progress, save custom versions, and organize into collections.Log In
$cat source_code/
cpp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct BigInt {
    static const int BASE = 1000000000;
    vector<int> v;

    BigInt() {}
    BigInt(ll val) { *this = val; }
    BigInt(const string &s) { *this = s; }

    int size() const { return (int)v.size(); }
    bool zero() const { return v.empty(); }

    ll val() const {
        ll ans = 0;
        for (int i = (int)v.size() - 1; i >= 0; i--)
            ans = ans * BASE + v[i];
        return ans;
    }

    void strip() { while (!v.empty() && v.back() == 0) v.pop_back(); }

    BigInt &operator=(ll val) {
        v.clear();
        for (; val > 0; val /= BASE) v.push_back(val % BASE);
        return *this;
    }

    BigInt &operator=(const string &s) {
        v.clear();
        for (int i = (int)s.size() - 1; i >= 0; i -= 9) {
            int st = max(0, i - 8);
            v.push_back(stoi(s.substr(st, i - st + 1)));
        }
        strip();
        return *this;
    }

    bool operator<(const BigInt &a) const {
        if (size() != a.size()) return size() < a.size();
        for (int i = size() - 1; i >= 0; i--)
            if (v[i] != a.v[i]) return v[i] < a.v[i];
        return false;
    }
    bool operator>(const BigInt &a) const { return a < *this; }
    bool operator==(const BigInt &a) const { return v == a.v; }
    bool operator<=(const BigInt &a) const { return !(a < *this); }
    bool operator>=(const BigInt &a) const { return !(*this < a); }

    BigInt operator+(const BigInt &a) const {
        BigInt res = *this;
        int carry = 0;
        for (int i = 0; i < (int)a.v.size() || carry; i++) {
            if (i == (int)res.v.size()) res.v.push_back(0);
            ll cur = res.v[i] + carry + (i < (int)a.v.size() ? a.v[i] : 0);
            res.v[i] = cur % BASE;
            carry = cur / BASE;
        }
        return res;
    }
    BigInt &operator+=(const BigInt &a) { return *this = *this + a; }

    BigInt operator-(const BigInt &b) const {
        BigInt res = *this;
        int borrow = 0;
        for (int i = 0; i < (int)b.v.size() || borrow; i++) {
            ll cur = res.v[i] - borrow - (i < (int)b.v.size() ? b.v[i] : 0);
            if (cur < 0) { cur += BASE; borrow = 1; }
            else borrow = 0;
            res.v[i] = cur;
        }
        res.strip();
        return res;
    }
    BigInt &operator-=(const BigInt &b) { return *this = *this - b; }

    BigInt operator*(const BigInt &a) const {
        if (zero() || a.zero()) return BigInt(0);
        BigInt res;
        res.v.resize(size() + a.size(), 0);
        for (int i = 0; i < size(); i++) {
            if (!v[i]) continue;
            ll carry = 0;
            for (int j = 0; j < (int)a.v.size() || carry; j++) {
                ll cur = res.v[i + j] + carry + 1LL * v[i] * (j < (int)a.v.size() ? a.v[j] : 0);
                res.v[i + j] = cur % BASE;
                carry = cur / BASE;
            }
        }
        res.strip();
        return res;
    }
    BigInt &operator*=(const BigInt &a) { return *this = *this * a; }

    BigInt &operator/=(ll a) {
        ll carry = 0;
        for (int i = (int)v.size() - 1; i >= 0; i--) {
            ll cur = v[i] + carry * BASE;
            v[i] = cur / a;
            carry = cur % a;
        }
        strip();
        return *this;
    }
    BigInt operator/(ll a) const { BigInt res = *this; res /= a; return res; }

    BigInt operator%(ll a) const {
        ll res = 0;
        for (int i = (int)v.size() - 1; i >= 0; i--)
            res = (res * BASE + v[i]) % a;
        return BigInt(res);
    }
    BigInt &operator%=(ll a) { return *this = *this % a; }

    friend ostream &operator<<(ostream &out, const BigInt &a) {
        if (a.zero()) return out << 0;
        out << a.v.back();
        for (int i = (int)a.v.size() - 2; i >= 0; i--)
            out << setfill('0') << setw(9) << a.v[i];
        return out;
    }

    friend istream &operator>>(istream &in, BigInt &a) {
        string s; in >> s; a = s; return in;
    }
};
128 linesutf-8
$cat explanation_notes.md
notes_viewer --renderedmarkdown (math enabled)

Big Integer

Arbitrary-precision non-negative integer stored in base 10910^9 (little-endian). Each "digit" holds up to 9 decimal digits.

Operations

  • Constructors — from long long, from decimal string, or default (zero)

  • Comparison<, >, ==, <=, >=

  • Addition / Subtraction+, -, +=, -=. Subtraction throws if result would be negative

  • Multiplication, = using schoolbook algorithm

  • Division / Modulo/, %, /=, %= by long long only (not BigInt-by-BigInt)

  • I/Ocin >> x and cout << x work directly
  • When to Use

  • When intermediate results exceed 64-bit range (>2631> 2^{63} - 1)

  • Large factorial computation, Fibonacci beyond long long, or problems that explicitly state "output can have thousands of digits"

  • C++ has no built-in big integer unlike Python/Java
  • Complexity

  • Addition / Subtraction — O(n)O(n) where nn is digit count (base 10910^9)

  • Multiplication — O(n2)O(n^2) schoolbook

  • Division / Modulo by llO(n)O(n)

  • Space — O(n)O(n)
  • Notes

  • This template only handles non-negative integers. Wrap with a sign flag if negatives are needed

  • For very large multiplications (n>104n > 10^4 digits), consider FFT/NTT-based multiply instead of schoolbook