C++大数类

BigInteger.h:
#ifndef _BIGINTEGER_H_
#define _BIGINTEGER_H_

#include <iostream>
#include <limits>
#include <string>

class BigInteger {
  public:
    BigInteger();

    BigInteger(long long);

    /**
     * @brief 以8/10/16进制字符串为参数构造BigInteger
     * ex: 070, 128, 0x1f
     */
    BigInteger(const std::string &);

    BigInteger(const BigInteger &);

    BigInteger &operator+();

    BigInteger operator-() const;

    BigInteger &operator++();

    BigInteger operator++(int);

    BigInteger &operator--();

    BigInteger operator--(int);

    BigInteger &operator=(const BigInteger &);

    BigInteger &operator+=(const BigInteger &);

    friend BigInteger operator+(const BigInteger &, const BigInteger &);

    BigInteger &operator-=(const BigInteger &);

    friend BigInteger operator-(const BigInteger &, const BigInteger &);

    BigInteger &operator*=(const BigInteger &);

    friend BigInteger operator*(const BigInteger &, const BigInteger &);

    BigInteger &operator/=(const BigInteger &);

    friend BigInteger operator/(const BigInteger &, const BigInteger &);

    BigInteger &operator%=(const BigInteger &);

    friend BigInteger operator%(const BigInteger &, const BigInteger &);

    friend std::istream &operator>>(std::istream &, const BigInteger &);

    friend std::ostream &operator<<(std::ostream &, const BigInteger &);

    friend bool operator==(const BigInteger &, const BigInteger &);

    friend bool operator!=(const BigInteger &, const BigInteger &);

    friend bool operator>(const BigInteger &, const BigInteger &);

    friend bool operator>=(const BigInteger &, const BigInteger &);

    friend bool operator<(const BigInteger &, const BigInteger &);

    friend bool operator<=(const BigInteger &, const BigInteger &);

  private:
    bool isNegtive;
    std::string mData;
};

#endif
BigInteger.cpp
#include "BigInteger.h"
#include <stdexcept>
#include <vector>
#include <cstring>
#include <deque>
#include <cassert>
using namespace std;

static bool convertBase(int base0, int base1, const char *from, std::string &to);

static int dexCompare(const std::string &a, const std::string &b);

static string Add(const std::string &a, const std::string &b);

static string Minus(const std::string &a, const std::string &b);

static string Multiply(const std::string &a, const std::string &b);

static string Divide(const std::string &a, const std::string &b);

BigInteger::BigInteger() : isNegtive(false), mData("0")
{
}

BigInteger::BigInteger(long long num) : isNegtive(num < 0), mData(to_string(abs(num)))
{
}

BigInteger::BigInteger(const std::string &sNum)
{
    size_t b = sNum.find_first_not_of(' ');
    if (b == string::npos)
        goto error;
    if (sNum[b] == '-') {
        isNegtive = true;
        b = sNum.find_first_not_of(' ', b + 1);
        if (b == string::npos)
            goto error;
    } else if (isdigit(sNum[b]))
        isNegtive = false;
    else
        goto error;

    int base;
    if (sNum[b] == '0') {
        if (b + 1 == sNum.size()) {
            isNegtive = false;
            mData = "0";
            return;
        }
        if (sNum[b + 1] == 'x' || sNum[b + 1] == 'X') {
            base = 16;
            b += 2;
        } else {
            base = 8;
            ++b;
        }
        if (b == sNum.size())
            goto error;
    } else
        base = 10;

    if (convertBase(base, 10, sNum.c_str() + b, mData))
        return;

    error:
    throw invalid_argument(sNum);
}

BigInteger::BigInteger(const BigInteger &rhs) : isNegtive(rhs.isNegtive), mData(rhs.mData)
{
}

BigInteger &BigInteger::operator=(const BigInteger &rhs)
{
    if (this != &rhs) {
        isNegtive = rhs.isNegtive;
        mData = rhs.mData;
    }
    return *this;
}

BigInteger &BigInteger::operator+()
{
    return *this;
}

BigInteger BigInteger::operator-() const
{
    BigInteger bi(*this);
    if (mData != "0")
        bi.isNegtive = !isNegtive;
    return bi;
}

BigInteger &BigInteger::operator++()
{
    *this += 1;
    return *this;
}

BigInteger BigInteger::operator++(int)
{
    BigInteger bi(*this);
    bi += 1;
    return bi;
}

BigInteger &BigInteger::operator--()
{
    *this -= 1;
    return *this;
}

BigInteger BigInteger::operator--(int)
{
    BigInteger bi(*this);
    bi -= 1;
    return bi;
}

bool operator==(const BigInteger &a, const BigInteger &b)
{
    return a.isNegtive == b.isNegtive && a.mData == b.mData;
}

bool operator!=(const BigInteger &a, const BigInteger &b)
{
    return !(a == b);
}

bool operator>(const BigInteger &a, const BigInteger &b)
{
    if (a.isNegtive != b.isNegtive)
        return !a.isNegtive;
    return a.isNegtive ? dexCompare(a.mData, b.mData) < 0 : dexCompare(a.mData, b.mData) > 0;
}

bool operator>=(const BigInteger &a, const BigInteger &b)
{
    return a > b || a == b;
}

bool operator<(const BigInteger &a, const BigInteger &b)
{
    return !(a >= b);
}

bool operator<=(const BigInteger &a, const BigInteger &b)
{
    return !(a > b);
}

BigInteger &BigInteger::operator+=(const BigInteger &rhs)
{
    if (isNegtive) {
        if (rhs.isNegtive) {
            mData = Add(mData, rhs.mData);
        } else {
            int cmp = dexCompare(mData, rhs.mData);
            if (cmp == 0) {
                isNegtive = false;
                mData = "0";
            } else if (cmp > 0) {
                mData = Minus(mData, rhs.mData);
            } else {
                isNegtive = false;
                mData = Minus(rhs.mData, mData);
            }
        }
    } else {
        if (!rhs.isNegtive)
            mData = Add(mData, rhs.mData);
        else {
            int cmp = dexCompare(mData, rhs.mData);
            if (cmp == 0) {
                isNegtive = false;
                mData = "0";
            } else if (cmp > 0) {
                mData = Minus(mData, rhs.mData);
            } else {
                isNegtive = true;
                mData = Minus(rhs.mData, mData);
            }
        }
    }
    return *this;
}

BigInteger operator+(const BigInteger &a, const BigInteger &b)
{
    BigInteger c(a);
    return c += b;
}

BigInteger &BigInteger::operator-=(const BigInteger &rhs)
{
    *this += -rhs;
    return *this;
}

BigInteger operator-(const BigInteger &a, const BigInteger &b)
{
    BigInteger c(a);
    return c -= b;
}

BigInteger &BigInteger::operator*=(const BigInteger &rhs)
{
    if (mData != "0") {
        if (rhs.mData == "0") {
            isNegtive = false;
            mData = "0";
        } else {
            isNegtive = (isNegtive && !rhs.isNegtive) || (!isNegtive && rhs.isNegtive);
            mData = Multiply(mData, rhs.mData);
        }
    }
    return *this;
}

BigInteger operator*(const BigInteger &a, const BigInteger &b)
{
    BigInteger c(a);
    return c *= b;
}

BigInteger &BigInteger::operator/=(const BigInteger &rhs)
{
    if (rhs.mData == "0")
        throw invalid_argument("divided by zero");
    if (mData != "0") {
        mData = Divide(mData, rhs.mData);
        if (mData == "0")
            isNegtive = false;
        else
            isNegtive = (isNegtive && !rhs.isNegtive) || (!isNegtive && rhs.isNegtive);
    }
    return *this;
}

BigInteger operator/(const BigInteger &a, const BigInteger &b)
{
    BigInteger c(a);
    return c /= b;
}

BigInteger &BigInteger::operator%=(const BigInteger &rhs)
{
    BigInteger r = *this / rhs;
    *this -= r * rhs;
    return *this;
}

BigInteger operator%(const BigInteger &a, const BigInteger &b)
{
    BigInteger c(a);
    return c %= b;
}

//BigInteger BigInteger::operator%(const BigInteger &rhs) const
//{
//    BigInteger bi(*this);
//    bi %= rhs;
//    return bi;
//}

std::istream &operator>>(std::istream &is, BigInteger &bi)
{
    string num;
    is >> num;
    try {
        BigInteger x(num);
        bi = x;
    } catch (invalid_argument &ia) {
        cerr << ia.what() << endl;
    }
    return is;
}

std::ostream &operator<<(std::ostream &os, const BigInteger &bi)
{
    if (bi.isNegtive)
        os << '-';
    return os << bi.mData;
}

static inline int char2int(char c)
{
    if (isdigit(c))
        return c - '0';
    if (c >= 'A' && c <= 'F')
        return c - 'A' + 10;
    if (c >= 'a' && c <= 'f')
        return c - 'a';
    return std::numeric_limits<int>::max();
}

static bool convertBase(int base0, int base1, const char *from, std::string &to)
{
    if (base0 == base1) {
        to.assign(from);
        return true;
    }
    int len = strlen(from);
    vector<int> a(len);
    deque<char> dq;
    for (int i = 0; i < len; ++i)
        if ((a[len - i - 1] = char2int(from[i])) >= base0)
            return false;
    while (len) {
        for (int i = len - 1; i; --i) {
            a[i - 1] += a[i] % base1 * base0;
            a[i] /= base1;
        }
        dq.push_front(a[0] % base1 + '0');
        a[0] /= base1;
        while (len && a[len - 1] == 0)
            --len;
    }
    to.assign(dq.cbegin(), dq.cend());
    return true;
}

/**
 * @brief 比较两个十进制大数的大小
 *
 * @param a
 * @param b
 * @return int
 */
static int dexCompare(const std::string &a, const std::string &b)
{
    if (a.size() != b.size())
        return a.size() > b.size() ? 1 : -1;
    return a.compare(b);
}

/**
 * @brief 相加两个正的十进制大数
 *
 * @param a
 * @param b
 */
static string Add(const std::string &a, const std::string &b)
{
    int i = a.size() - 1, j = b.size() - 1, feed = 0;
    deque<char> dq;
    while (i >= 0 && j >= 0) {
        int x = a[i--] - '0' + b[j--] - '0' + feed;
        dq.push_front(x % 10 + '0');
        feed = x / 10;
    }
    while (i >= 0) {
        int x = a[i--] - '0' + feed;
        dq.push_front(x % 10 + '0');
        feed = x / 10;
    }
    while (j >= 0) {
        int x = b[j--] - '0' + feed;
        dq.push_front(x % 10 + '0');
        feed = x / 10;
    }
    while (feed) {
        dq.push_front(feed % 10 + '0');
        feed /= 10;
    }
    return string(dq.begin(), dq.end());
}

static string Minus(const std::string &a, const std::string &b)
{
    if (a == b)
        return "0";
    assert(dexCompare(a, b) > 0);
    int i = a.size() - 1, j = b.size() - 1, borrow = 0;
    deque<char> dq;
    while (i >= 0 && j >= 0) {
        int x = a[i--] - '0' - (b[j--] - '0') - borrow;
        if (x < 0) {
            borrow = 1;
            x += 10;
        } else
            borrow = 0;
        dq.push_front(x + '0');
    }
    while (i >= 0) {
        int x = a[i--] - '0' - borrow;
        if (x < 0) {
            borrow = 1;
            x += 10;
        } else
            borrow = 0;
        dq.push_front(x + '0');
    }
    while (!dq.empty() && dq.front() == '0')
        dq.pop_front();
    return string(dq.begin(), dq.end());
}

static string Multiply(const std::string &a, int b)
{
    if (a == "0" || b == 0)
        return "0";
    int i = a.size() - 1, feed = 0;
    deque<char> dq;
    while (i >= 0) {
        int x = (a[i--] - '0') * b + feed;
        dq.push_front(x % 10 + '0');
        feed = x / 10;
    }
    while (feed) {
        dq.push_front(feed % 10 + '0');
        feed /= 10;
    }
    return string(dq.begin(), dq.end());
}

static string Multiply(const std::string &a, const std::string &b)
{
    assert(a != "0" && b != "0");
    string res = "0";
    for (int j = b.size() - 1, n = 0; j >= 0; --j, ++n) {
        string temp = Multiply(a, b[j] - '0');
        if (temp != "0") {
            temp += string(n, '0');
            res = Add(res, temp);
        }
    }
    return res;
}

static int tryDivide(const std::string &a, const std::string &b)
{
    assert(dexCompare(a, b + "0") < 0);
    int l = 0, r = 10;
    while (l + 1 < r) {
        int mid = (l + r) / 2;
        dexCompare(Multiply(b, mid), a) > 0 ? r = mid : l = mid;
    }
    return l;
}

static string Divide(const std::string &a, const std::string &b)
{
    assert(!b.empty() && b != "0");
    if (dexCompare(a, b) < 0)
        return "0";

    string curr = b.size() == 1 ? "0" : a.substr(0, b.size() - 1), res;
    size_t p = b.size() - 1;

    while (p < a.size()) {
        if (curr == "0")
            curr = string(1, a[p++]);
        else
            curr.push_back(a[p++]);
        int r = tryDivide(curr, b);
        if (!res.empty() || r)
            res.push_back(r + '0');
        curr = Minus(curr, Multiply(b, r));
    }

    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值