美丽的高精度计算

对于一个很懒且计算能力不强的人来说,计算器是一个不错的东西,两个数字的计算更是再简单不过了:为了填充我的博客,下面是简单的计算:
#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");
	}//消除前导0
	for(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,b
	lena=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--;//前导0
	for(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--;//前导0
	for(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;
				}
				else
					printf("%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

猜你喜欢

转载自blog.csdn.net/C20191904/article/details/72574676