1.高精度减法
下面的这个是来自于洛谷上面的题目:

2.代码实现
下面的这个是具体的代码,我认为还是有点复杂的,简单的看一下吧:
cpp
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int a[N], b[N], c[N];
int la, lb, lc;
// 比大小
bool cmp(string& x, string& y)
{
// 先比较长度
if(x.size() != y.size()) return x.size() < y.size();
// 再按照 字典序 的方式比较
return x < y;
}
// 高精度减法的模板 - c = a - b
void sub(int c[], int a[], int b[])
{
for(int i = 0; i < lc; i++)
{
c[i] += a[i] - b[i]; // 对应位相减,然后处理借位
if(c[i] < 0)
{
c[i + 1] -= 1; // 借位
c[i] += 10;
}
}
// 处理前导零
while(lc > 1 && c[lc - 1] == 0) lc--;
}
int main()
{
string x, y; cin >> x >> y;
// 比大小
if(cmp(x, y))
{
swap(x, y);
cout << '-';
}
// 1. 拆分每一位,然后逆序放在数组中
la = x.size(); lb = y.size(); lc = max(la, lb);
for(int i = 0; i < la; i++) a[la - i - 1] = x[i] - '0';
for(int i = 0; i < lb; i++) b[lb - i - 1] = y[i] - '0';
// 2. 模拟减法的过程
sub(c, a, b); // c = a - b
// 输出结果
for(int i = lc - 1; i >= 0; i--) cout << c[i];
return 0;
}
1)我觉得在这个问题里面可以抓住两条主线:相较于我们的这个高精度的加法的主线;
第一点:变化的是什么,没有变化的是什么;
第二点:我们的这个减法里面的主要模块的划分;
2)先来谈谈这个第一点的主线,变化的是什么,这个里面多了cmp函数,因为需要保证这个事大数减去小数,不变的就是我们的这个思路是不变的,还是字符串转换成为数组倒序的存放到我们的这个对应的数组里面去,然后进行这个位数的处理过程;
3)首先看一下这个第一大模块,就是这个sub方法,或者叫做函数,这个里面的swap实际上就是想要保证这个事大数据减去小数据,仅此而已,这个需要先去判断这个位数,位数不一样的话,直接根据这个位数多的确定大小即可;
位数一样的时候,按照这个字典序进行比较即可,如果需要进行交换,说明这个本来说是小数减去大数,因此这个cmp判断里面有这个cout负号的过程,这个就是为了保证我们的这个绝对值不变,但是这个负号需要改变,这个是数学知识,我不想多去赘述;
4)sub函数是这个代码里面的核心和我们的这个加法里面的add函数类似,注意这个里面的+=,这个和我们的高精度加法里面的这个事类似的,然后这个if事在判断我们的这个借位情况,比如这个类似于2-8之类的情况,我们需要进行借位,但是这个需要判断,只有两个数据相减出现负数的时候才说明这个需要借位;
5)借位的时候就是前面的这个c[i+1]减去1即可,不要问我这个为什么是i+1,因为这个顺序和我们的这个字符串里面的这个顺序是相反的,大家自己去理解一下,我点到为止;
6)然后就是这个0的处理,我们的加法运算里面是这个高位的进位处理;
减法里面是0的处理。例如我们的997-995,这个时候计算之后就是002,但是这个高位的0显然是不需要进行输出的,因此这个需要保证我们的这个指针lc指向的是我们的这个结果里面的第一个非零的数据,也就是我们的这个while里面的c[lc-1]的判断条件;
但是还有一个情况,例如我们的999-999,这个时候就是000,这个时候我们是需要输出结果的,因此这个事需要保留一个0的,也就是我们的这个while条件里面的这个lc>1的情况,只有当这两个条件同时满足的时候,这个代码才会执行;
也就是我们的这个数据有位数,而且这个前一位是0,我们才会进行这个lc--的处理;
7)变化之中找不变,进行对比总结,我认为才是正确的学习之道;