高精度运算
众所周知,c++有一种变量叫int_64……
谁还用高精度呢
好吧NOI与CSP貌似不支持int_64的样子
完结撒花
高精度运算,是指参与运算的数(加数,减数,因子……)范围大大超出了标准数据类型(整型,实型)能表示的范围的运算。例如,求两个20000位的数的和。这时,就要用到高精度算法了。
高精度加法
思想
将两个加数作为string型输入或存储,再将其转化为int型数组,每个数位上只记录[0,9]的数。计算时将两个数组相同数位相加并处理进位
变量名说明
sa,sb:存储两个加数的string型数组
la,lb,lc:两个加数的位数与和的位数
a,b,c:两个加数与和
具体过程
转化字符串
for(int i=0;i<la;i++){ //注意要倒序存储
a[la-i-1]=sa[i]-'0'; //char与int间转化
}
for(int i=0;i<lb;i++){
b[lb-i-1]=sb[i]-'0';
}
初步确定和的位数
lc=la>lb ?la: lb; //三位运算符
各数位相加并处理进位
for(int i=0;i<lc;i++){
c[i]+=a[i]+b[i];
if(c[i]>9){ //处理进位
c[i+1]+=1;
c[i]-=10;
}
}
位数处理
if(c[lc]>9) lc++;
完整代码
#include<bits/stdc++.h>
using namespace std;
int la,lb,lc,a[510],b[510],c[510];
char x[510],y[510];
int main(){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
scanf("%s",x);
scanf("%s",y);
la=strlen(x);
lb=strlen(y);
lc=la>lb? 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';
for(int i=0;i<lc;i++){
c[i]+=a[i]+b[i];
if(c[i]>=10){
c[i+1]++;
c[i]-=10;
}
}
if(c[lc]>0) lc++;
for(int i=lc-1;i>=0;i--) printf("%d",c[i]);
return 0;
}
典例
高精度减法
思想
与高精度加法相近,唯一不同是需要处理的不是进位,而是借位
具体过程
借位
if(c[i]<0){ //处理借位
c[i+1]-=1;
c[i]+=10;
}
使最高位非零
for(int i=lc-1;i>=0;i--){ //使结果最高位非零
if(c[i]==0) lc--;
else break;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
char sa[210],sb[210];
int la,lb,lc,a[210],b[210],c[210]; //范围自取
int main(){
scanf("%s",sa);
scanf("%s",sb);
la=strlen(sa);
lb=strlen(sb);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<la;i++){ //char与int转化
a[la-i-1]=sa[i]-'0';
}
for(int i=0;i<lb;i++){
b[lb-i-1]=sb[i]-'0';
}
lc=la>lb ?la: lb; //确定结果位数上限
memset(c,0,sizeof(c));
for(int i=0;i<lc;i++){
c[i]=a[i]-b[i]+c[i];
if(c[i]<0){ //处理借位
c[i+1]-=1;
c[i]+=10;
}
}
if(c[lc]<0) lc--;
for(int i=lc-1;i>=0;i--){ //使结果最高位非零
if(c[i]==0) lc--;
else break;
}
for(int i=lc-1;i>=0;i--){
printf("%d",c[i]);
}
return 0;
}
典例
似乎没有典例……好吧可以去其他OJ上找模板题
高精度乘法
思想
与高精度加法相似其实高精度思想都差不多
具体过程
高精度乘法
for(int i=0;i<la;i++){
for(int j=0;j<lb;j++){
f=x[i]*y[j]; //f:记录结果
jw=f/10; //jw:记录进位
f%=10;
w=i+j; //精髓:w:每次数组的下标
//这里可以参考竖式乘法,i位与j位相乘应存储在i+j位
z[w]+=f;
z[w+1]+=jw+z[w]/10;//处理进位
z[w]%=10;
}
}
完整代码
#include<bits/stdc++.h>
using namespace std;
long long la,lb,lc,x[20010],y[20010],z[20010],w,jw,f; //注意数据大小
char a[20010],b[20010];
int main(){
scanf("%s",a);
scanf("%s",b);
la=strlen(a);
lb=strlen(b);
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(z,0,sizeof(z));
for(int i=0;i<la;i++) x[la-i-1]=a[i]-'0';
for(int i=0;i<lb;i++) y[lb-i-1]=b[i]-'0';
for(int i=0;i<la;i++){
for(int j=0;j<lb;j++){
f=x[i]*y[j]; //f:记录结果
jw=f/10; //jw:记录进位
f%=10;
w=i+j; //w:每次数组的下标
z[w]+=f;
z[w+1]+=jw+z[w]/10;//处理进位
z[w]%=10;
}
}
lc=la+lb;
while(z[lc]==0) lc--;
if(lc<0) printf("%d",0);
else{
for(int i=lc;i>=0;i--) printf("%lld",z[i]);
}
return 0;
}