上一篇博客:计蒜客T1098:大整数加法(高精度加法详解)
写在前面:大家好!我是
ACfun
,我的昵称来自两个单词Accepted
和fun
。我是一个热爱ACM的蒟蒻。这篇博客来讲解一下高精度问题中的减法。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正,感谢大家的不吝赐教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油,冲鸭!
用知识改变命运,用知识成就未来!加油 (ง •̀o•́)ง (ง •̀o•́)ง
本题链接:大整数减法
求两个大的正整数相减的差。
共 2 行,第 1 行是被减数 a,第 2 行是减数 b(a > b)。每个大整数不超过 200 位,不会有多余的前导零。
一行,即所求的差。
输出时每行末尾的多余空格,不影响答案正确性
9999999999999999999999999999999999999
9999999999999
9999999999999999999999990000000000000
#include
#include
using namespace std;
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 -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
// 去掉结果中的前导零
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main(){
string a, b;
vector<int> A, B;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
vector<int> C;
C = sub(A, B);
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
return 0;
}
大整数减法又叫高精度减法,对于该问题首先我们要考虑如何在计算机中存储大整数。高精度问题简介和大数的存储方式在上一篇博客:
计蒜客T1098:大整数加法(高精度加法详解) 中已经详细的叙述了,这里就不再赘述了。
做大整数减法首先我们需要判断一下 减数 和 被减数 哪一个更大
。比如大整数 a - b,如果 a > b,那么结果为正数,在输出时我们就不用考虑输出负号;如果 a < b,那么结果为负数,我们需要将 a - b 改为 - (b - a) 来计算,我们只需要计算 b - a,最后在输出时先输出一个负号
即可。因为在该题题目中保证了 被减数 a 大于减数 b (a>b) 所以我们就可以省略这一步直接进行相减即可。
我们先设计一个比较两个数大小的函数 cmp() 和实现大整数减法的函数 sub();这里的 cmp() 函数要根据情况来写
,比如本题为求两个大的正整数
相减的差,那么在 cmp(a,b) 中我们首先判断一下数组 a 和 b 的长度,长度长的肯定是更大的。如果长度相等那么我们就逐位比较,直到碰到相同数位上数字不相等的情况时返回比较结果。
判断出 a 和 b 的大小之后,我们每次保证在传参时是数更大的在第一个参数,更小的那个数在第二个参数,这样我们就保证了每次在sub()函数中实现大数减去小数。即如果 a > b 那么我们就传入 sub(a, b)。如果 a < b,那么我们就传入sub(b, a)。
// 判断是否有 A >= B
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;
}
在 sub(a, b) 函数中我们用vector
作为返回值,使用引用传递的方式传入参数(因为使用引用方式传参就不需要额外的进行拷贝参数,更省时间和空间)。然后我们先定义一个 vector 数组 C 作为存储结果数组,定义一个变量 int t = 0 作为借位的标记。因为在主函数传参时我们保证了 a 一定是大于 b 的,所以我们循环遍历 a,从个位开始逐位相减。
这里的 t 是实现大整数减法的关键,首先我们计算一下当前位的值为多少比如我们开始计算两个数的个位相减,我们使用之前定义的变量 t 来存储结果,即 t = A[0] - B[0] - t,这里后面的 t 即为借位,如果 t 的结果大于 等于0 ,说明在两个数的个位 A[0] >= B[0] 那么就不需要借位那么我们将 t 设置为 0 下一次计算十位的时候依旧是 t = A[1] - B[1] - t ,之后我们将这个结果存储在C[0]上,即结果的个位。如果 t 的结果小于 0 ,那么说明需要借位,那么我们就将结果 +10 。然后将 t 设置为 1,证明我们借位了,在下一次t = A[1] - B[1] - t 时需要多减去一个 1。这里还要注意在相减的过程中我们要判断一下B的该位是否存在,存在我们才相减,不存在就不进行相减,所以在我们分开来算t = A[1] - B[1] - t,具体实现方法请看下边的大整数减法模板。
最后注意去掉结果中的前导零
,然后返回数组 C 进行输出即可。
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 -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
// 去掉结果中的前导零
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
#include
#include
using namespace std;
// 判断是否有 A >= B
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 -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
// 去掉结果中的前导零
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main(){
string a, b;
vector<int> A, B;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
vector<int> C;
if (cmp(A, B)) {
C = sub(A, B);
} else {
C = sub(B, A);
cout << "-";
}
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
return 0;
}