思路
我们只需要普通地模拟数字的减法就可以了。
我们这里为了方便,不管怎么样我们都是让大的数减去小的数。
这里需要注意如果是小数减大数需要加负号。
这里如果看不懂的话可以看下完整代码
例子
18 - 34 = -16
第一步
读取数字,将数字用vector存储起来。
第二步
模拟减法的时候我们是从数字尾部开始模拟的,所以为了方便我们可以先将vector反转。
第三步
我们需要让大的数减去小的数,这样会更加便捷。
如果像是该例子,小的减大的,我们只需要让大的减小的,结果加一个负号就可以了。
第四步
从初始位置开始相减,也就是4 - 8 = -4。(此时已经把18和34互换了,也就是34-18)
第五步
当前位置的数字则是**(4 - 8 + 10) % 10**。
这里特别说明下,为什么要+10再%10呢。
- +10是为了计算当前位的数字,比如4-8,不够,那么就当前位向前面借一位,也就是+10+4-8,得到的是6。
- %10主要是为了让+10向下取模,因为有可能是大的减小的,比如8-4=4,如果你+10了之后不取模那就是8-4+10=14了,所以要取模。
第六步
指针前移,继续第三步,之不过要多考虑上一步借的位。
第七步
由于一开始我们是翻转之后计算的,所以结尾要翻转计算出来的答案。
完整代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool cmp(vector<int>& v1, vector<int>& v2){
//如果长度不一样,直接返回长度大的
if(v1.size() != v2.size()) return v1.size() > v2.size();
for(int i = v1.size() - 1; i >= 0; i--){
if(v1[i] != v2[i]){
return v1[i] > v2[i];
}
}
return true;
}
vector<int> sub(vector<int>& v1, vector<int>& v2){
vector<int> res;
int cur = 0;//记录借位
for(int i = 0; i < v1.size(); i++){
cur = v1[i] - cur;//首先减去上一步的借位
if(i < v2.size()) cur -= v2[i];
res.push_back((cur + 10) % 10);//保证当前值为正整个位数
if(cur < 0) cur = 1;//如果当前值小于0,那么需要借位
else cur = 0;
}
// 去掉前缀0
while(res.back() == 0 && res.size() > 1) res.pop_back();
return res;
}
int main(){
string s1, s2;//对应数字用字符串读取
cin >> s1 >> s2;
vector<int> v1, v2;
//将对应字符串存储到vector里面,并且进行翻转。
for(int i = s1.size() - 1; i >= 0; i--) v1.push_back(s1[i] - '0');
for(int i = s2.size() - 1; i >= 0; i--) v2.push_back(s2[i] - '0');
vector<int> ans;
//保证大的减小的
if(cmp(v1, v2)){
ans = sub(v1, v2);
}else{
ans = sub(v2, v1);
//小的减大的需要加 - 号
cout << '-';
}
//反着输出,等价于翻转
for(int i = ans.size() - 1; i >= 0; i--) {
cout << ans[i];
}
return 0;
}
最后
我的上一篇文章讲了高精度加法,有兴趣的可以看看:D
C++实现高精度加法。保姆式教学。
下一篇讲高精度乘法:D
C++实现高精度乘法。图解+保姆式教学。