目录
在csp-j的复赛中,经常需要使用到高精度算法。为什么要使用高精度算法呢?因为int类型最高只能到21亿,就算开到最大的usgined long long也只能写到18446744073709551615,对于那些100位,1000位的数据,我们无法用数字类型存储,只能使用字符串的形式来存储。对于这些位数极多的数据进行运算,我们就需要“高精度运算”。
高精度加法
对于加法的运算,想必各位无论是已经工作了的,还是已经六十多岁的老年人了,都一定还记得加法如何运算。
a[i] | 6 | 5 | 2 | 3 | 6 | 9 | 0 | 1 | 2 |
---|---|---|---|---|---|---|---|---|---|
b[i] | 9 | 3 | 9 | 6 | 6 | 3 | 1 | ||
c[i] | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 |
sum[i] | 5 | 9 | 1 | 0 | 3 | 3 | 2 | 1 | 2 |
这里的程序比较简单,可以使用s1和s2来存储输入进来的两个高精度数据。同时,将位数多的排在前面,方便计算。
cin >> s1 >> s2;
if (s1.length()<s2.length()) { //将位数多的排在前面
swap(s1,s2);
}
接下来,将两个字符串逐个逆转拆位,存放进数组里 ,就像前面的表格一样。
m=1;
for (int i=s1.length()-1;i>=0;i--){ //将s1分位存储
a[m]=s1[i]-'0';
m++;
}m=1;
for (int i=s2.length()-1;i>=0;i--){ //将s2分位存储
b[m]=s2[i]-'0';
m++;
接下来我们就要逐位相加,求出最后的结果了。
敲重点了!这里由于存在进位,需要另外一个数组c[]来存储进位。
c[]需要把十位提取,sum[]需要把个位提取。
for (int i=1;i<=s1.length()+1;i++){
c[i+1]=(a[i]+b[i]+c[i])/10; //存储进位数据
sum[i]=(a[i]+b[i]+c[i])%10; //存储实际数据
}if(sum[s1.length()+1]!=0) //判断最高位是否有进位
cout << sum[s1.length()+1];
最后,倒序输出结果。
for (int i=s1.length();i>0;i--){ //输出
cout << sum[i];
}
全部代码如下:
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
string s1,s2;
int a[10005],b[10005],c[10005],sum[10005],m;
int main(){
cin >> s1 >> s2;
if (s1.length()<s2.length()) { //将位数多的排在前面
swap(s1,s2);
} m=1;
for (int i=s1.length()-1;i>=0;i--){ //将s1分位存储
a[m]=s1[i]-'0';
m++;
}m=1;
for (int i=s2.length()-1;i>=0;i--){ //将s2分位存储
b[m]=s2[i]-'0';
m++;
}for (int i=1;i<=s1.length()+1;i++){
c[i+1]=(a[i]+b[i]+c[i])/10; //存储进位数据
sum[i]=(a[i]+b[i]+c[i])%10; //存储实际数据
}if(sum[s1.length()+1]!=0) //判断最高位是否有进位
cout << sum[s1.length()+1];
for (int i=s1.length();i>0;i--){ //输出
cout << sum[i];
}
return 0;
}
最后再重温一遍思路:从最低位开始,每位每位地相加,留下个位,十位作为进位加到前面一位。
高精度减法①(保证a>b)
对于此类高精度减法,我们保证被减数大于减数。这类是最基本的高精度减法,在很多方面上都与高精度加法类似。
下为写入数据与转换数据代码:
cin >> s1 >> s2;
m=1;
for (int i=s1.length()-1;i>=0;i--){
a[m]=s1[i]-'0';
m++;
}m=1;
for (int i=s2.length()-1;i>=0;i--){
b[m]=s2[i]-'0';
m++;
}
让我们重温一下,减法的借位条件是怎么样的?在被减数减去上级借位数之后,如果小于减数,就需要向上一级借10来补。因此,在这个过程中,结果一定是一位数。
for (int i=1;i<=s1.length();i++){
if(a[i]<b[i]+c[i]) {
a[i+1]--;
a[i]+=10;
}sum[i]=a[i]-b[i];
}
接下来,需要把最高位的0给去掉。
p=s1.length();
while(sum[p]==0){
p--;
}
最后输出,就完事了。
//高精度减法最初版本:保证a>b
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
string s1,s2;
int a[10005],b[10005],c[10005],sum[10005],m;
int main(){
cin >> s1 >> s2;
m=1;
for (int i=s1.length()-1;i>=0;i--){
a[m]=s1[i]-'0';
m++;
}m=1;
for (int i=s2.length()-1;i>=0;i--){
b[m]=s2[i]-'0';
m++;
}for (int i=1;i<=s1.length();i++){
if(a[i]<b[i]+c[i]) {
a[i+1]--;
a[i]+=10;
}sum[i]=a[i]-b[i];
}p=s1.length();
while(sum[p]==0){
p--;
}if(sum[s1.length()+1]!=0)
cout << sum[s1.length()+1];
for (int i=p;i>0;i--){
cout << sum[i];
}
return 0;
}
最后重温高精度减法基本思路:从最低位开始,逐位相减。如果不够,就往前面借1为10,再继续计算。