一个高精度通用模板
我知道,很多人是有的,但是我认为我可以分享一下,有助于新人了解高精度。
代码
#include <bits/stdc++.h>
using namespace std;
class owl_num
{
private:vector<long long> digits;bool is_negative;public:owl_num() : is_negative(false) {}owl_num(const string &s){if (s.empty()){digits = {0};is_negative = false;}else{string num = s;if (s[0] == '-'){is_negative = true;num = s.substr(1);}else{is_negative = false;}digits = read(num);normalize();}}owl_num(long long num){if (num < 0){is_negative = true;num = -num;}else{is_negative = false;}digits = read(to_string(num));}owl_num(const vector<long long> &v, bool neg = false) : digits(v), is_negative(neg){normalize();}friend ostream &operator<<(ostream &os, const owl_num &num){if (num.is_negative && !(num.digits.size() == 1 && num.digits[0] == 0)){os << '-';}for (long long i = num.digits.size() - 1; i >= 0; --i){os << num.digits[i];}return os;}friend istream &operator>>(istream &is, owl_num &num){string s;is >> s;if (s.empty()){num = owl_num();}else{if (s[0] == '-'){num.is_negative = true;num.digits = num.read(s.substr(1));}else{num.is_negative = false;num.digits = num.read(s);}num.normalize();}return is;}owl_num operator-() const{owl_num result = *this;if (!(digits.size() == 1 && digits[0] == 0)){result.is_negative = !is_negative;}return result;}owl_num operator+(const owl_num &other) const{if (is_negative == other.is_negative){return owl_num(add(digits, other.digits), is_negative);}if (maxs(digits, other.digits) == digits){return owl_num(sub(digits, other.digits), is_negative);}return owl_num(sub(other.digits, digits), other.is_negative);}owl_num operator-(const owl_num &other) const{return *this + (-other);}owl_num operator*(const owl_num &other) const{bool result_neg = is_negative != other.is_negative;owl_num result(mul(digits, other.digits), result_neg);result.normalize();return result;}owl_num operator*(long long num) const{bool result_neg = is_negative != (num < 0);if (num < 0)num = -num;owl_num result(mul_ll(digits, num), result_neg);result.normalize();return result;}owl_num operator/(const owl_num &other) const{bool result_neg = is_negative != other.is_negative;auto [quotient, remainder] = divmod(digits, other.digits);quotient.is_negative = result_neg && !(quotient.digits.size() == 1 && quotient.digits[0] == 0);return quotient;}owl_num operator/(long long num) const{bool result_neg = is_negative != (num < 0);if (num < 0)num = -num;auto [quotient, remainder] = divmod_ll(digits, num);quotient.is_negative = result_neg && !(quotient.digits.size() == 1 && quotient.digits[0] == 0);return quotient;}owl_num operator%(const owl_num &other) const{auto [quotient, remainder] = divmod(digits, other.digits);remainder.is_negative = is_negative && !(remainder.digits.size() == 1 && remainder.digits[0] == 0);return remainder;}long long operator%(long long num) const{if (num < 0)num = -num;auto [quotient, remainder] = divmod_ll(digits, num);long long mod = remainder.to_long_long();if (is_negative && mod != 0){mod = num - mod;}return mod;}owl_num operator^(long long owlposer) const{if (owlposer < 0){throw runtime_error("Negative exponent not supported");}bool result_neg = is_negative && (owlposer % 2 != 0);return owl_num(owlpos(digits, owlposer), result_neg);}bool operator<(const owl_num &other) const{if (is_negative != other.is_negative){return is_negative;}if (is_negative){return maxs(digits, other.digits) == digits && !(*this == other);}return maxs(digits, other.digits) == other.digits && !(*this == other);}bool operator<(long long num) const{return *this < owl_num(num);}bool operator>(const owl_num &other) const{if (is_negative != other.is_negative){return other.is_negative;}if (is_negative){return maxs(digits, other.digits) == other.digits && !(*this == other);}return maxs(digits, other.digits) == digits && !(*this == other);}bool operator>(long long num) const{return *this > owl_num(num);}bool operator<=(const owl_num &other) const{return !(*this > other);}bool operator<=(long long num) const{return *this <= owl_num(num);}bool operator>=(const owl_num &other) const{return !(*this < other);}bool operator>=(long long num) const{return *this >= owl_num(num);}bool operator==(const owl_num &other) const{return digits == other.digits && is_negative == other.is_negative;}bool operator==(long long num) const{return *this == owl_num(num);}bool operator!=(const owl_num &other) const{return !(*this == other);}bool operator!=(long long num) const{return *this != owl_num(num);}owl_num &operator=(const owl_num &other) = default;owl_num &operator=(const string &s){if (s.empty()){digits = {0};is_negative = false;}else{if (s[0] == '-'){is_negative = true;digits = read(s.substr(1));}else{is_negative = false;digits = read(s);}normalize();}return *this;}owl_num &operator=(long long num){if (num < 0){is_negative = true;num = -num;}else{is_negative = false;}digits = read(to_string(num));normalize();return *this;}owl_num &operator+=(const owl_num &other){*this = *this + other;return *this;}owl_num &operator+=(long long num){*this = *this + owl_num(num);return *this;}owl_num &operator-=(const owl_num &other){*this = *this - other;return *this;}owl_num &operator-=(long long num){*this = *this - owl_num(num);return *this;}owl_num &operator*=(const owl_num &other){*this = *this * other;return *this;}owl_num &operator*=(long long num){*this = *this * num;return *this;}owl_num &operator/=(const owl_num &other){*this = *this / other;return *this;}owl_num &operator/=(long long num){*this = *this / num;return *this;}owl_num &operator%=(const owl_num &other){*this = *this % other;return *this;}long long operator%=(long long num){long long mod = (*this % num);*this = owl_num(mod);return mod;}owl_num &operator^=(long long owlposer){*this = *this ^ owlposer;return *this;}owl_num abs() const{return owl_num(digits);}long long to_long_long() const{long long num = 0;for (long long i = digits.size() - 1; i >= 0; --i){num = num * 10 + digits[i];}return is_negative ? -num : num;}private:void normalize(){while (digits.size() > 1 && digits.back() == 0){digits.pop_back();}if (digits.size() == 1 && digits[0] == 0){is_negative = false;}}pair<owl_num, owl_num> divmod(const vector<long long> &a, const vector<long long> &b) const{if (b.size() == 1 && b[0] == 0){throw runtime_error("Division by zero");}owl_num dividend(a);owl_num divisor(b);owl_num quotient("0");owl_num remainder("0");for (long long i = a.size() - 1; i >= 0; --i){remainder = remainder * owl_num("10") + owl_num(vector<long long>{a[i]});long long digit = 0;while (remainder >= divisor){remainder -= divisor;digit++;}quotient = quotient * owl_num("10") + owl_num(vector<long long>{digit});}quotient.normalize();remainder.normalize();return make_pair(quotient, remainder);}pair<owl_num, owl_num> divmod_ll(const vector<long long> &a, long long b) const{if (b == 0){throw runtime_error("Division by zero");}long long remainder = 0;vector<long long> quotient;for (long long i = a.size() - 1; i >= 0; --i){remainder = remainder * 10 + a[i];quotient.push_back(remainder / b);remainder %= b;}reverse(quotient.begin(), quotient.end());while (quotient.size() > 1 && quotient.back() == 0){quotient.pop_back();}return make_pair(owl_num(quotient), owl_num(vector<long long>{remainder}));}vector<long long> mul(const vector<long long> &a, const vector<long long> &b) const{vector<long long> c(a.size() + b.size(), 0);for (long long i = 0; i < a.size(); ++i){long long carry = 0;for (long long j = 0; j < b.size() || carry; ++j){long long current = c[i + j] + a[i] * (j < b.size() ? b[j] : 0) + carry;c[i + j] = current % 10;carry = current / 10;}}while (c.size() > 1 && c.back() == 0){c.pop_back();}return c;}vector<long long> mul_ll(const vector<long long> &a, long long b) const{vector<long long> c;long long carry = 0;for (long long digit : a){long long product = digit * b + carry;c.push_back(product % 10);carry = product / 10;}while (carry > 0){c.push_back(carry % 10);carry /= 10;}while (c.size() > 1 && c.back() == 0){c.pop_back();}return c;}vector<long long> add(const vector<long long> &a, const vector<long long> &b) const{vector<long long> c;long long t = 0;for (long long i = 0; i < a.size() || i < b.size() || t; ++i){if (i < a.size()){t += a[i];}if (i < b.size()){t += b[i];}c.push_back(t % 10);t /= 10;}while (c.size() > 1 && c.back() == 0){c.pop_back();}return c;}vector<long long> sub(const vector<long long> &a, const vector<long long> &b) const{vector<long long> c;long long t = 0;for (long long i = 0; i < a.size() || i < b.size(); ++i){if (i < a.size()){t += a[i];}if (i < b.size()){t -= b[i];}if (t < 0){t += 10;c.push_back(t);t = -1;}else{c.push_back(t);t = 0;}}while (c.size() > 1 && c.back() == 0){c.pop_back();}return c;}vector<long long> owlpos(const vector<long long> &a, long long owlposer) const{if (owlposer == 0){return {1};}if (owlposer == 1){return a;}vector<long long> result = {1};vector<long long> base = a;while (owlposer > 0){if (owlposer % 2 == 1){result = mul(result, base);}base = mul(base, base);owlposer /= 2;}return result;}vector<long long> maxs(const vector<long long> &a, const vector<long long> &b) const{if (a.size() > b.size()){return a;}if (b.size() > a.size()){return b;}for (long long i = b.size() - 1; i >= 0; --i){if (b[i] != a[i]){if (b[i] > a[i]){return b;}if (a[i] > b[i]){return a;}}}return a;}vector<long long> read(const string &s) const{vector<long long> a;for (long long i = s.size() - 1; i >= 0; --i){a.push_back(s[i] - '0');}return a;}
};
使用方法:可以像int一样使用高精度owl_num
目前已经支持基本运算符号,后续可能会补充