高精度模板 class封装 加减乘除模幂运算

下午很无聊的打了一个这个,,,,

起因是写dp题的时候正好要用到高精 而我是一个非常讨厌写高精度的人 于是一气之下码了

嗯这个是我的class

class BigInteger {
private:
    vector < int > digits;
    bool isNegative;
    void removeLeadingZeros() {
        while (digits.size() > 1 && digits.back() == 0) digits.pop_back();
        if (digits.empty()) {
            digits.push_back(0);
            isNegative = false;
        } else if (digits.size() == 1 && digits[0] == 0) isNegative = false;
    }
    int compareAbs(const BigInteger& other) const {
        if (digits.size() != other.digits.size()) return digits.size() > other.digits.size() ? 1 : -1;
        for (int i = digits.size() - 1; i >= 0; --i)
            if (digits[i] != other.digits[i]) return digits[i] > other.digits[i] ? 1 : -1;
        return 0;
    }
public:
    BigInteger() : isNegative(false) { digits.push_back(0); }
    BigInteger(const string& s) {
        isNegative = false;
        int start = 0;
        if (!s.empty() && s[0] == '-') {isNegative = true; start = 1;}
        digits.clear();
        for (int i = s.size() - 1; i >= start; --i) {
            if (!isdigit(s[i])) throw invalid_argument("Invalid number string");
            digits.push_back(s[i] - '0');
        }
        removeLeadingZeros();
    }
    BigInteger(long long num) {
        isNegative = num < 0;
        num = std::abs(num);
        digits.clear();
        if (num == 0) digits.push_back(0);
        else while (num > 0) {digits.push_back(num % 10); num /= 10;}
        removeLeadingZeros();
    }
    BigInteger abs() const {
        BigInteger result = *this;
        result.isNegative = false;
        return result;
    }
    friend bool operator<(const BigInteger& a, const BigInteger& b) {
        if (a.isNegative != b.isNegative) return a.isNegative;
        return a.isNegative ? a.compareAbs(b) > 0 : a.compareAbs(b) < 0;
    }
    friend bool operator>(const BigInteger& a, const BigInteger& b) { return b < a; }
    friend bool operator<=(const BigInteger& a, const BigInteger& b) { return !(a > b); }
    friend bool operator>=(const BigInteger& a, const BigInteger& b) { return !(a < b); }
    friend bool operator==(const BigInteger& a, const BigInteger& b) { return a.isNegative == b.isNegative && a.digits == b.digits;}
    friend bool operator!=(const BigInteger& a, const BigInteger& b) { return !(a == b); }
    BigInteger operator-() const {
        BigInteger result = *this;
        if (result != BigInteger(0)) result.isNegative = !result.isNegative;
        return result;
    }
    friend BigInteger operator+(const BigInteger& a, const BigInteger& b) {
        if (a.isNegative == b.isNegative) {
            BigInteger result;
            result.digits.resize(max(a.digits.size(), b.digits.size()) + 1, 0);
            int carry = 0;
            for (int i = 0; i < result.digits.size(); ++i) {
                int sum = carry;
                if (i < a.digits.size()) sum += a.digits[i];
                if (i < b.digits.size()) sum += b.digits[i];
                result.digits[i] = sum % 10;
                carry = sum / 10;
            }
            result.isNegative = a.isNegative;
            result.removeLeadingZeros();
            return result;
        } else {
            if (a.compareAbs(b) >= 0) {
                BigInteger result;
                result.digits.resize(a.digits.size(), 0);
                int borrow = 0;
                for (int i = 0; i < a.digits.size(); ++i) {
                    int sub = a.digits[i] - borrow;
                    if (i < b.digits.size()) sub -= b.digits[i];
                    if (sub < 0) sub += 10, borrow = 1;
                    else borrow = 0;
                    result.digits[i] = sub;
                }
                result.isNegative = a.isNegative;
                result.removeLeadingZeros();
                return result;
            } else return b + a;
        }
    }
    friend BigInteger operator-(const BigInteger& a, const BigInteger& b) {return a + (-b);}
    friend BigInteger operator*(const BigInteger& a, const BigInteger& b) {
        BigInteger result;
        result.digits.resize(a.digits.size() + b.digits.size(), 0);
        for (int i = 0; i < a.digits.size(); ++i) {
            int carry = 0;
            for (int j = 0; j < b.digits.size(); ++j) {
                int temp = result.digits[i + j] + a.digits[i] * b.digits[j] + carry;
                result.digits[i + j] = temp % 10;
                carry = temp / 10;
            }
            if (carry > 0) result.digits[i + b.digits.size()] += carry;
        }
        result.isNegative = a.isNegative != b.isNegative;
        result.removeLeadingZeros();
        return result;
    }
    friend BigInteger operator/(const BigInteger& a, const BigInteger& b) {
        if (b == BigInteger(0)) throw runtime_error("Division by zero");
        BigInteger dividend = a.abs();
        BigInteger divisor = b.abs();
        if (dividend < divisor) return BigInteger(0);
        vector rev_dividend(dividend.digits.rbegin(), dividend.digits.rend());
        BigInteger current_remainder;
        vector quotient_digits;
        for (int digit : rev_dividend) {
            current_remainder = current_remainder * BigInteger(10) + BigInteger(digit);
            int d = 9;
            BigInteger product;
            for (; d >= 0; --d) {
                product = divisor * d;
                if (product <= current_remainder) break;
            }
            quotient_digits.push_back(d);
            current_remainder = current_remainder - product;
        }
        reverse(quotient_digits.begin(), quotient_digits.end());
        BigInteger quotient;
        quotient.digits = quotient_digits;
        quotient.isNegative = a.isNegative != b.isNegative;
        quotient.removeLeadingZeros();
        return quotient;
    }
    friend BigInteger operator%(const BigInteger& a, const BigInteger& b) {
        BigInteger quotient = a / b;
        return a - quotient * b;
    }
    friend ostream& operator<<(ostream& os, const BigInteger& num) {
        if (num.isNegative && num != BigInteger(0)) os << '-';
        for (auto it = num.digits.rbegin(); it != num.digits.rend(); ++it) os << *it;
        return os;
    }
    BigInteger pow(int exponent) const {
    	if (exponent < 0) throw invalid_argument("BigInteger pow: Negative exponent not supported");
    	if (exponent == 0) {
    	    if (*this == BigInteger(0)) throw invalid_argument("BigInteger pow: 0^0 undefined");
    	    return BigInteger(1);
    	}
    	BigInteger result(1);
    	BigInteger base = *this;
    	int exp = exponent;
    	while (exp > 0) {
    	    if (exp % 2 == 1) result = result * base;
    	    base = base * base;
    	    exp /= 2;
    	}
    	return result;
	}
};

用法是这样的

//加减乘除 写了重载运算符 直接用就可以
string s1, s2; cin >> s1 >> s2;
BigInteger a(s1), b(s2);
cout << a + b << "\n" << a - b << "\n" << a * b << "\n" << a / b << "\n";

快速幂 复杂度是O(log)的 用法这样

//表示a的b次方
string s; cin >> s;
BigInteger a(s); int b;
cout << a.pow(b) << "\n";

我真厉害(((((   造福后人

你可能感兴趣的:(c++,算法,高精度,学习)