一、高精度算法(下文分别给出模板)
原理:
当一个数很大时,大到普通的 int 存不下时,可以考虑用数组来存储,即数组中一个位置存放一位。
但是对于数组而言,一个数顺序存入数组后,对其相加减是很简单的。但是当要进位时,是相当麻烦的。因为要将整个数组全都往后移动一位,将最高位的进位位置空出来,这个操作是 O(n) 的。
有一种方法可以很好的解决进位的问题。就是将这个数的个位数存至数组中的第一位(即 a[0]),最高位存入数组的最后一位(a[n - 1])。这样在处理进位时可以直接在数组的最后一位添加即可。在输出时倒序输出即可。
二、高精度加法
根据以上原理,我们可以很简单就模拟出具体实现方式。
举个例子:求 9724 + 377 后的值。
将两个数分别存入 a 数组和 b 数组中,如下图:
运算的话就很简单了。将第一个位置相加,如果大于 9 就要进一位(这一步可以利用取模来实现)。再将第二个位置的数相加,同时加上前一位的进位,再观察是否大于 9 。以此类推便可求出最终答案。
高精度加法代码模板
// 利用c ++ 中的 vector 来存放数。
vector<int> add(vector<int> a, vector<int> b)
{
vector<int> c;
int t = 0;
for(int i = 0; i < a.size() || i < b.size(); i ++ )
{
if(i < a.size()) t = t + a[i];
if(i < b.size()) t = t + b[i];
c.push_back(t / 10);
t = t % 10;
}
if(t) c.push_back(t);
return c;
}
三 、高精度减法
减法与加法类似,区别的话具体有两点
- 在于是大的数减小的数还是小的数减大的数,这两种情况的共同点在于他们相减后的绝对值是相等的,所以在运算前判断数的大小即可。
- 又可能两个数相等或者高位数值相等,那么在相减的过程中会产生 0 ,并且这个 0 是在高位的,在输出时会输出 0 ,那么得要去除这个 0 。若是要求出产生 0 的位置,这个步骤是相对繁琐的。这个时候用数组倒序存数的又一大优势来了,可以直接利用 pop_back() 去除最后的元素(即最高位的元素)。
高精度减法代码模板
// 判断两个数的大小
bool cmp(vector<int> a, vector<int> 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 true;
}
// 两数相减
vector<int> sub(vector<int> a, vector<int> b)
{
vector<int> c;
int t = 0;
for(int i = 0; i < a.size(); i ++ )
{
t = a[i] - t;
if(i < b.size()) t = t - b[i];
c.push_back(t / 10);
if(t < 0) t = 1;
else t = 0;
}
// 去除高位 0
while(c.size() > 1 && c.back() == 0) c.pop_back();
return c;
}
四、高精度乘法
由于高精度乘于高精度应用不多,这里只给出高精度乘与低精度。
高精度乘法与高精度加法基本类似,下文直接给出模板。
高精度乘法代码模板
vector<int> mul(vector<int> a, int b)
{
vector<int> c;
int t = 0;
for(int i = 0; i < a.size(); i ++ )
{
t = t + a[i] * b;
c.push_back(t % 10);
t = t / 10;
}
if(t) c.push_back(t);
while(c.size() > 1 && c.back() == 0) c.pop_back();
return c;
}
五、高精度除法
这里的情况同样是高精度与低精度,用高精度除以低精度。
高精度除法代码模板
vector<int> div(vector<int> &a, int b, int &r)
{
vector<int> c;
r = 0;
for (int i = a.size() - 1; i >= 0; i -- )
{
r = r * 10 + a[i];
c.push_back(r / b);
r %= b;
}
reverse(c.begin(), c.end());
while (c.size() > 1 && c.back() == 0) c.pop_back();
return c;
}