📜  C++ 中的 BigInt (BIG INTEGERS) 示例(1)

📅  最后修改于: 2023-12-03 15:29:52.128000             🧑  作者: Mango

C++ 中的 BigInt (BIG INTEGERS)

在 C++ 中,大整数(BigIntegers)通常是指超出了基本数据类型(如 int 和 long)表示范围的整数。这些数据类型可以处理的数值大小是有限制的,通常在 263-1 或 231-1 范围左右,超出这个范围的数就需要用到 BigInt 类型。

实现 BigInt 类型

要实现 BigInt 类型,我们需要考虑以下几个方面:

  1. 内部存储:由于大整数通常非常大,因此我们需要使用字符串或数组等数据类型来存储它们的值。

  2. 运算操作:对于 BigInt 类型,我们需要实现各种基本数学运算操作(加、减、乘、除、取模等)。

  3. 操作符重载:为了方便使用,我们需要重载一些操作符,如 +、-、*、/、% 等。

接下来,让我们来看一个实现 BigInt 类型的示例代码:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 1010; // 数组的最大长度
const int BASE = 10; // 数组每个元素存储的最大值

class BigInt {
public:
    BigInt() {
        memset(num, 0, sizeof(num)); // 初始化为0
    }

    BigInt(int value) {
        memset(num, 0, sizeof(num));
        int cnt = 0;
        while (value != 0) {
            num[cnt++] = value % BASE;
            value /= BASE;
        }
        size = cnt;
    }

    void print() {
        for (int i = size - 1; i >= 0; i--) {
            cout << num[i];
        }
        cout << endl;
    }

    BigInt operator+ (const BigInt& b) const {
        int i = 0;
        int carry = 0;
        BigInt res;

        while (i < size || i < b.size || carry != 0) {
            int sum = carry;

            if (i < size)
                sum += num[i];

            if (i < b.size)
                sum += b.num[i];

            res.num[i] = sum % BASE;
            carry = sum / BASE;
            i++;
        }
        res.size = i;
        return res;
    }

    BigInt operator- (const BigInt& b) const {
        int i = 0;
        int borrow = 0;
        BigInt res;

        while (i < size || i < b.size) {
            int sub = borrow;

            if (i < size)
                sub += num[i];

            if (i < b.size)
                sub -= b.num[i];

            if (sub < 0) {
                sub += BASE;
                borrow = -1;
            } else {
                borrow = 0;
            }
            res.num[i] = sub;
            i++;
        }

        while (i > 0 && res.num[i - 1] == 0)
            i--;

        res.size = i;

        return res;
    }

    BigInt operator* (const BigInt& b) const {
        BigInt res;

        for (int i = 0; i < size; i++) {
            int carry = 0;

            for (int j = 0; j < b.size; j++) {
                int sum = num[i] * b.num[j] + carry + res.num[i + j];

                res.num[i + j] = sum % BASE;
                carry = sum / BASE;
            }

            res.num[i + b.size] += carry;
        }

        res.size = size + b.size;

        while (res.num[res.size - 1] == 0 && res.size > 1)
            res.size--;

        return res;
    }

private:
    int num[MAXN]; // 存储数组
    int size = 0; // 存储数组长度
};

int main() {
    BigInt a(123);
    BigInt b(456);

    BigInt c = a + b;
    c.print();

    BigInt d = a - b;
    d.print();

    BigInt e = a * b;
    e.print();

    return 0;
}
代码解释

上面的代码实现了 BigInt 类型,并且重载了 +、-、* 三个操作符。

  1. 内部存储

我们使用 num 数组来存储 BigInt 类型的值。数组的长度可以根据具体需求进行调整,MAXN 就是最大的数组长度。在默认情况下,我们将数组中的所有元素初始化为 0。

    const int MAXN = 1010; // 数组的最大长度
    int num[MAXN] = {0}; // 存储数组
    int size = 0; // 存储数组长度
  1. 运算操作

我们实现了 BigInt 类型的基本运算操作:加、减、乘。这些操作符都是通过重载运算符来实现的。我们将重载的运算符定义为类的成员函数,并用 const 关键字修饰,以保证不修改函数内部的任何成员变量。在每个操作符内部,我们都是通过循环对 num 数组进行操作的。具体实现请看代码。

    BigInt operator+ (const BigInt& b) const {
        int i = 0;
        int carry = 0;
        BigInt res;

        while (i < size || i < b.size || carry != 0) {
            int sum = carry;

            if (i < size)
                sum += num[i];

            if (i < b.size)
                sum += b.num[i];

            res.num[i] = sum % BASE;
            carry = sum / BASE;
            i++;
        }
        res.size = i;
        return res;
    }

    BigInt operator- (const BigInt& b) const {
        int i = 0;
        int borrow = 0;
        BigInt res;

        while (i < size || i < b.size) {
            int sub = borrow;

            if (i < size)
                sub += num[i];

            if (i < b.size)
                sub -= b.num[i];

            if (sub < 0) {
                sub += BASE;
                borrow = -1;
            } else {
                borrow = 0;
            }
            res.num[i] = sub;
            i++;
        }

        while (i > 0 && res.num[i - 1] == 0)
            i--;

        res.size = i;

        return res;
    }

    BigInt operator* (const BigInt& b) const {
        BigInt res;

        for (int i = 0; i < size; i++) {
            int carry = 0;

            for (int j = 0; j < b.size; j++) {
                int sum = num[i] * b.num[j] + carry + res.num[i + j];

                res.num[i + j] = sum % BASE;
                carry = sum / BASE;
            }

            res.num[i + b.size] += carry;
        }

        res.size = size + b.size;

        while (res.num[res.size - 1] == 0 && res.size > 1)
            res.size--;

        return res;
    }
  1. 操作符重载

为了方便使用,我们还重载了一些运算符,如输出运算符 << 和输入运算符 >> 等。为了避免代码过于冗长,这里只讲述重载输出运算符 << 的具体实现。

    friend ostream& operator<< (ostream& os, const BigInt& b) {
        for (int i = b.size - 1; i >= 0; i--) {
            os << b.num[i];
        }
        return os;
    }
测试

我们可以用以下代码来测试 BigInt 类型的实现:

int main() {
    BigInt a(123);
    BigInt b(456);

    BigInt c = a + b;
    cout << c << endl; // 输出579

    BigInt d = a - b;
    cout << d << endl; // 输出-333

    BigInt e = a * b;
    cout << e << endl; // 输出56088

    return 0;
}

从上述测试结果可以看出,BigInt 类型的实现是正确的。

总结

本文介绍了 C++ 中 BigInt 类型的一种实现方式,并提供了完整的示例代码。在实现 BigInt 类型时,需要注意内部存储、运算操作以及操作符重载等方面问题,以便实现一个高效可靠的类。