高精度
支持高位数的运算系统.
简介 #
高精度是支持高位数的运算系统. 本章仅介绍最常用的正整数运算系统.
构造 #
在 vector<int>
容器内保存每位数字,并实现自动处理进位.
vector<int>
的位数要从 $0$ 记起(第 $0$ 位,第 $1$ 位,$\cdots$).
struct Wint:vector<int> { // 以 vector 为基类
Wint(int n = 0) { // 初始化为 0
push_back(n);
upgrade();
}
Wint& upgrade() { // 处理进位
while (!empty() && !back())
pop_back(); // 去除最高位多余的 0
if (empty())
return *this;
for (int i = 1; i < size(); i ++) { // 满 10 进 1
(*this)[i] += (*this)[i - 1] / 10;
(*this)[i - 1] %= 10;
}
while (back() >= 10) { // 最高位 >= 10 时,新增一位
push_back(back() / 10);
(*this)[size() - 2] %= 10;
}
return *this;
}
};
输入 #
取出字符串的每一位,倒序存入数组.
Wint init(string s) {
Wint n;
for (int i = s.size() - 1; i >= 0; i --)
n.push_back(s[i] - '0');
return n;
}
输出 #
数据是倒序储存的,故倒序输出.
void print(Wint n) {
if (n.empty()) printf("0");
for (int i = n.size() - 1; i >= 0; i --)
printf("%d", n[i]);
}
比较 #
先比较位数. 若位数相同,则从高位到低位逐位比较.
bool operator != (const Wint &a, const Wint &b) {
if (a.size() != b.size())
return true;
for (int i = a.size() - 1; i >= 0; i --)
if (a[i] != b[i])
return true;
return false;
}
bool operator == (const Wint &a, const Wint &b) {
return !(a != b);
}
bool operator < (const Wint &a, const Wint &b) {
if (a.size() != b.size())
return a.size() < b.size();
for (int i = a.size() - 1; i >= 0; i --)
if (a[i] != b[i])
return a[i] < b[i];
return false;
}
bool operator > (const Wint &a, const Wint &b) {
return b < a;
}
bool operator <= (const Wint &a, const Wint &b) {
return !(a > b);
}
bool operator >= (const Wint &a, const Wint &b) {
return !(a < b);
}
加法 #
从低位到高位,将两数对应位置相加.
先实现 +=
方法,节省传参时间.
Wint& operator += (Wint &a, const Wint &b) {
if (a.size() < b.size())
a.resize(b.size());
for (int i = 0; i < b.size(); i ++)
a[i] += b[i];
return a.upgrade();
}
Wint operator + (Wint a, const Wint &b) {
return a += b;
}
减法 #
返回差的绝对值. 从低位到高位,将两数对应位置相减. 不够减要借位.
Wint& operator -= (Wint &a, Wint b) {
if (a < b) swap(a,b);
for (int i = 0; i < b.size(); i ++) {
if (a[i] < b[i]) { // 需要借位
a[i + 1] --;
a[i] += 10;
}
a[i] -= b[i];
}
return a.upgrade();
}
Wint operator - (Wint a, const Wint &b) {
return a -= b;
}
乘法 #
将 $a$ 的第 $i$ 位乘 $b$ 的第 $j$ 位累加在答案的第 $i+j$ 位上.
Wint operator * (const Wint &a, const Wint &b) {
Wint n;
n.assign(a.size( ) + b.size() - 1, 0);
for (int i = 0; i < a.size(); i ++)
for (int j = 0; j < b.size(); j ++)
n[i + j] += a[i] * b[j];
return n.upgrade();
}
Wint& operator *= (Wint &a, const Wint &b) {
return a = a * b;
}
除法 #
先实现带余除法函数,再重载符号方法.
将 $b$ 和 $a$ 最高位对齐,重复相减,统计减的次数.
Wint divmod(Wint &a, const Wint &b) {
Wint ans;
for (int t = a.size() - b.size(); a >= b; t --) {
Wint d;
d.assign(t + 1, 0);
d.back() = 1;
Wint c = b * d;
while (a >= c) {
a -= c;
ans += d;
}
}
return ans;
}
Wint operator / (Wint a, const Wint &b) {
return divmod(a, b);
}
Wint& operator /= (Wint &a, const Wint &b) {
return a = a / b;
}
Wint& operator %= (Wint &a, const Wint &b) {
divmod(a, b);
return a;
}
Wint operator % (Wint a, const Wint &b) {
return a %= b;
}