美丽的高精度计算

来源:互联网 发布:知乎帖子怎么删除 编辑:程序博客网 时间:2024/05/21 09:05
对于一个很懒且计算能力不强的人来说,计算器是一个不错的东西,两个数字的计算更是再简单不过了:为了填充我的博客,下面是简单的计算:
#include<cstdio>int main(){   int a,b;   char c;   scanf("%d %c %d",&a,&c,&b);   if(c=='+') printf("%d",a+b);   if(c=='-') printf("%d",a-b);   if(c=='*') printf("%d",a*b);   if(c=='/') printf("%d",a/b);   if(c=='%') printf("%d",a%b);return 0;} 

相信这个东西就算是刚学的初学者也能看懂,所以就没必要解释了;

but 当我们信心满满输入一大串数进行运算的时候,尴尬的一幕产生了:

因为int(甚至long long)类型已经存不下

这时:就产生了我们牛逼的高精度运:

高精度运算的原理特别简单,就是用计算机分步把竖式运算的方法表示出来,在对进位退位的细节进行处理,就形成的简单的高精度运算;


我要讲的主要是高精度的加、减、乘,因为这些运算比较简单(再说除法我也不怎么会):

直接上代码,大家自行理解;


高精加:

#include<cstdio>#include<cstring>int a[205],b[205],c[205];//输入的a,b;c是辅助   char a1[205],b1[205];int main(){int lena,lenb,lenc,i,x,t;fgets(a1,205,stdin);fgets(b1,205,stdin);//用字符串的形式输入a,b数组(既需要计算的数字a,b)lena=strlen(a1)-1;  lenb=strlen(b1)-1;//a,b的长度(类比竖式运算)for(i=0;i<=lena-1;i++)    a[lena-i]=a1[i]-48;for(i=0;i<=lenb-1;i++)    b[lenb-i]=b1[i]-48;//转数字(进行运算)lenc=1;x=0;while(lenc<=lena||lenc<=lenb)  {c[lenc]=a[lenc]+b[lenc]+x;x=c[lenc]/10;c[lenc]%=10;lenc++;}//相加,进位c[lenc]=x;//单独做最低位          t=lenc;for(i=1;i<=t;i++){if(c[lenc]==0)   lenc--;if(lenc==0)       printf("0");}//消除前导0for(i=lenc;i>=1;i--) printf("%d",c[i]);//输出运算结果printf("\n");return 0;}

个人觉得高精加就十分够用了,毕竟关键时刻还可以写成函数循环转乘法(如果你真的不会的话);


高精减:

#include<cstdio>#include<cstring>int a[205],b[205],c[205];char a1[205],b1[205],c1[205];int main(){int lena,lenb,lenc,i;gets(a1);gets(b1);if((strlen(a1)<strlen(b1))||(strlen(a1)==strlen(b1)&&strcmp(a1,b1)<0)){strcpy(c1,a1);strcpy(a1,b1);strcpy(b1,c1);printf("-");}//a比b小,结果为负,交换a,blena=strlen(a1);lenb=strlen(b1);//同样是关键的长度for(i=0;i<=lena-1;i++)a[lena-i]=a1[i]-48;for(i=0;i<=lenb-1;i++)b[lenb-i]=b1[i]-48;//转数字lenc=1;while(lenc<=lena||lenc<=lenb){if(a[lenc]<b[lenc]){a[lenc]+=10;a[lenc+1]--;}//借位c[lenc]=a[lenc]-b[lenc];lenc++;//相减}while(lenc>1&&c[lenc]==0)lenc--;//前导0for(i=lenc;i>=1;i--)printf("%d",c[i]);//输出结果printf("\n");return 0;}

减法比较简单,自行理解




高精乘

#include<cstdio>#include<cstring>int main(){char z[200],yy[200];int w[200]={},a[200]={},n[400]={},lena,lenb,lenc,i,j,x;gets(z);gets(yy);lena=strlen(z);lenb=strlen(yy);//同理for(i=0;i<=lena-1;i++)w[lena-i]=z[i]-48;for(i=0;i<=lenb-1;i++)a[lenb-i]=yy[i]-48;//转换for(i=1;i<=lena;i++){x=0;for(j=1;j<=lenb;j++){n[i+j-1]=w[i]*a[j]+x+n[i+j-1];x=n[i+j-1]/10;n[i+j-1]=n[i+j-1]%10;}n[i+lenb]=x;}//计算,进位lenc=lena+lenb;while(n[lenc]==0&&lenc>1)lenc--;//前导0for(i=lenc;i>=1;i--)printf("%d",n[i]);//输出}


高精除法比较困难(for me)所以就不在此讲解了;

再为大家补充几个比较常用的高精运算(不作讲解)

阶乘(对照noi题库1.6 14 题看)

#include<cstdio>const int N=10005;const int M=100000;int s[N]={1,1},i,j,x,len=1;int main(){scanf("%d",&x);for(i=2;i<=x;i++){for(j=1;j<=len;j++)s[j]*=i;for(int j=1;j<=len;j++){s[j+1]+=s[j]/M;s[j]%=M;}len++;while(s[len]){s[len+1]=s[len]/M;s[len]%=M;len++;}}while(s[len]==0&&len>1)len--;printf("%d",s[len]);for(i=len-1;i>=1;i--)printf("%05d",s[i]);}


分解因子(对照noi题库1.6 13题看)

#include<cstdio>#include<cstring>int main(){char a[35];   scanf("%s",a);    int x, y=1;for (int k = 2; k <= 9; k++){x= 0;for (int i = 0; a[i] != 0; i++){x= x* 10 + (a[i] - '0');x %= k;}if (x== 0){if (y){printf("%d ",k);y = 0;}elseprintf("%d ",k);}}    if (y)printf("none");printf("\n");    return 0;}

阶乘和(对照noi题库1.6 15题看)

#include<cstdio>#include<climits>const int MX=100000;int s[100005]={1},sum[100005]={1};int i,j,k,n,t=0,tt=0,c=0,tmp;void mul(){c=0;for(j=0;j<=t;j++){tmp=s[j]*i+c;if(tmp>=MX){s[j]=tmp%MX;c=tmp/MX;if(j+1>t){s[j+1]=c;t++;break;}}else{s[j]=tmp;c=0;}}}void add(){c=0;if(tt<t) tt=t;for(j=0;j<=tt;j++){tmp=sum[j]+s[j]+c;if(tmp>=MX){sum[j]=tmp%MX;c=tmp/MX;if(j+1>tt){sum[j+1]=c;tt++;break;}}else{sum[j]=tmp;c=0;}}}void pri(){printf("%d",sum[tt]);for(k=tt-1;k>=0;k--)printf("%05d",sum[k]);printf("\n");}int main(){scanf("%d",&n);for(i=2;i<=n;i++){mul();add();}pri();}


这就是我掌握的一些基础的高精度运算,希望有帮助(如果不够,调数组大小),当然,这些模板都是要非常熟练的基础知识......好好记吧.....

the end

原创粉丝点击