高精度加减法
我们在运算时,需要为变量赋予不同的数据类型,例如int,double,long long等。但是,当我们在面对一些极大的数字时,现有的数据类型并不支持我们进行加减运算。此时,我们可以运用高精度的算法进行计算。
高精度加减法的原理就是:我们将数字的每一位都拆开,装入一个数组,然后对数组的每一位单独进行运算。然而,我们在输入数据时一般是输入一整个数字而不会一位一位地输入,那么该怎么办呢?
解决方案是先把数字存入一个string中,然后将string中的每一位依次存入数组中。中间字符到整数的转化,我们可以运用ASCII码的一个技巧,任意数字字符减去字符0的结果就是对应的整数,例如'8' - '0' = 8。
针对加法,我们按位相加,记得进位即可。 下面是详细的代码示例:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
//高精度加法:两个不超过1万位的数相加
int a[10010], b[10010], c[10010];
string s1, s2;
int init(int x[]){ //读入数据,并且返回数据的位数
string s;
cin >> s;
int l = s.size(); //数据的长度
for(int i = 0; i < l; ++i){ //倒着存,x[0]存储个位数字
x[i] = s[l - 1 -i] - '0'; //字符数字减去字符0,就是对应数值
}
return l;
}
int main(){
int la = init(a); //处理数据1
int lb = init(b); //处理数据2
int lc = max(la, lb) + 1; //结果的最大位数(最高位可能进位1,如果没有进位,则填入前导0)
for(int i = 0; i < max(la, lb); ++i){
c[i] += a[i] + b[i];
if(c[i] >= 10){
c[i] -= 10;
c[i + 1]++;
}
}
//去掉前导0(0024-->24)
--lc; //下标是0~lc-1,所以这里直接减一
while(c[lc] == 0 && lc > 0){
--lc;
}//lc就是目前最高位的下标,输出的范围lc~0
for(int i = lc; i >= 0; --i){
cout << c[i];
}
printf("\n");
return 0;
}
针对减法,我们不可以一上来就进行初始化,因为减法是有可能减出负数的,所以我们要先判断输入的s1和s2的大小关系,如果s1更小,那么要先输出一个负号然后交换s1和s2。这样就可以按位相减,记得不够减还要借位,最后去掉前导0就可以输出了。 下面是详细的代码示例:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
//高精度加法:两个不超过1万位的数相减
int a[10010], b[10010], c[10010];
string s1, s2;
int init(int x[], string s){ //读入数据,并且返回数据的位数
int l = s.size(); //数据的长度
for(int i = 0; i < l; ++i){ //倒着存,x[0]存储个位数字
x[i] = s[l - 1 -i] - '0'; //字符数字减去字符0,就是对应数值
}
return l;
}
int main(){
cin >> s1 >> s2;
if((s1.size() < s2.size()) || (s1.size() == s2.size() && s1 < s2)){ //s1比s2长 或者 s1与s2按位比较,s1更大
cout << '-';
swap(s1, s2);
}
//大减小
int la = init(a, s1);
int lb = init(b, s2);
int lc = max(la, lb);
for(int i = 0; i < lc; ++i){
c[i] += a[i] - b[i];
if(c[i] < 0){
c[i] += 10;
--c[i + 1];
}
}
//去掉前导0(0024-->24)
--lc; //下标是0~lc-1,所以这里直接减一
while(c[lc] == 0 && lc > 0){
--lc;
}//lc就是目前最高位的下标,输出的范围lc~0
for(int i = lc; i >= 0; --i){
cout << c[i];
}
printf("\n");
return 0;
}