关于高精度问题的自我总结
高精度这个问题说起来很头疼啊,也算是最近接触的算法,这里做个总结吧,做个自己的模板也好看。
加法
先是加法吧,很简单,网上也有很多的资料,包括UVA上的BIG的第一题也就高精度加法,就是数组处理,贴个自己经常用的模板:
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 10000 + 10
#define ZERO 0
int main()
{
char x[MAX_SIZE],y[MAX_SIZE];
int a[MAX_SIZE]={ZERO},b[MAX_SIZE]={ZERO};
int L1,L2;
int i,j;
gets(x); /*输入一个数字,处理成字符串*/
L1=strlen(x);
gets(y);
L2=strlen(y);
for(i=0,j=L1-1;i<L1;i++,j--)
a[j]=x[i]-'0';/*将字符串元素转化为数组储存*/
for(i=0,j=L2-1;i<L2;i++,j--)
b[j]=y[i]-'0';
/*这里需要倒序储存,仔细一想就知道了*/
for(i=0;i<(L1>L2?L1:L2);i++)
{
a[i]+=b[i];
if(a[i]>=10)
{
a[i]%=10;
a[i+1]++;
}
}
/*这里就是进位了,加法的一次最多进一位,所以直接进就可以了*/
for(i=MAX_SIZE-10,j=0;i>=0;i--)
{
if(j==1)
printf("%d",a[i]);
else if(a[i]!=0)
{
printf("%d",a[i]);
j=1;
}
} /*这里就是跳过空格了*/
if(j==0)
printf("0\n");
/*特例的考虑*/
}
乘法的话也没什么,就是考虑最后进位吧,不能像加法一样,乘一次就进一次
也是贴个自己用的模板.
乘法
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 10000 + 10
#define ZERO 0
int main()
{
char x[MAX_SIZE],y[MAX_SIZE];
int a[MAX_SIZE]={ZERO},b[MAX_SIZE]={ZERO};
int sum[MAX_SIZE]={ZERO};
int L1,L2;
int i,j;
gets(x); /*输入一个数字,处理成字符串*/
L1=strlen(x);
gets(y);
L2=strlen(y);
for(i=0,j=L1-1;i<L1;i++,j--)
a[j]=x[i]-'0';/*将字符串元素转化为数组储存*/
for(i=0,j=L2-1;i<L2;i++,j--)
b[j]=y[i]-'0';
/*这里需要倒序储存,仔细一想就知道了*/
for(i=0;i<L1;i++)
for(j=0;j<L2;j++)
sum[i+j]+=a[i]*b[j];
/*下面就是核心了,进位问题*/
for(i=0;i<MAX_SIZE;i++)
{
sum[i+1]+=sum[i]/10;
sum[i]%=10;
}
for(i=MAX_SIZE-10,j=0;i>=0;i--)
{
if(j==1)
printf("%d",sum[i]);
else if(sum[i]!=0)
{
printf("%d",sum[i]);
j=1;
}
} /*这里就是跳过空格了*/
if(j==0)
printf("0\n");
/*特例的考虑*/
}
减法
这个和加法同理吧,先判断哪个数比较大,永远用大减下,之后看是负的加个‘-’
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 10000 + 10
#define ZERO 0
int judge(int x[],int y[]) /*判断哪个数比较大*/
{
int i;
for(i=MAX_SIZE-10;i>=0;i--)
{
if(x[i]>y[i])
return 1;
if(x[i]<y[i])
return 0;
}
return 1;
}
int main()
{
char x[MAX_SIZE],y[MAX_SIZE];
int a[MAX_SIZE]={ZERO},b[MAX_SIZE]={ZERO};
int c[MAX_SIZE]={ZERO};
int L1,L2;
int i,j,w;
gets(x); /*输入一个数字,处理成字符串*/
L1=strlen(x);
gets(y);
L2=strlen(y);
for(i=0,j=L1-1;i<L1;i++,j--)
a[j]=x[i]-'0';/*将字符串元素转化为数组储存*/
for(i=0,j=L2-1;i<L2;i++,j--)
b[j]=y[i]-'0';
/*这里需要倒序储存,仔细一想就知道了*/
w=judge(a,b);
for(i=0;i<(L1>L2?L1:L2);i++)
{
if(w==1) /*用大数去减小数*/
c[i]=a[i]-b[i];
else
c[i]=b[i]-a[i];
}
/*最后处理进位问题*/
for(i=0;i<MAX_SIZE;i++)
if(c[i]<0)
{
c[i]+=10;
c[i+1]--;
}
if(w==0)
printf("-");
for(i=MAX_SIZE-10,j=0;i>=0;i--)
{
if(j==1)
printf("%d",c[i]);
else if(c[i]!=0)
{
printf("%d",c[i]);
j=1;
}
} /*这里就是跳过空格了*/
if(j==0)
printf("0\n");
/*特例的考虑*/
}
阶乘
根据刘汝佳的书上的改了一个自己用的舒服的模板
#include<stdio.h>
#define ZERO 0
#define MAX_SIZE 1000 + 10
int main()
{
int n;
int i,j,k;
int array[MAX_SIZE]={ZERO};/*初始化*/
scanf("%d",&n);
array[0]=1;
for(i=2;i<=n;i++)
{
for(j=0;j<MAX_SIZE;j++)
{
array[j]*=i;
}
/*每次乘完就进位*/
for(j=0;j<MAX_SIZE;j++)
{
array[j+1]+=array[j]/10;
array[j]%=10;
}
}
for(i=MAX_SIZE-10,k=0;i>=0;i--)
{/*跳过0逆向输出*/
if(k==1)
printf("%d",array[i]);
else if(array[i]!=0)
{
k=1;
printf("%d",array[i]);
}
}
}
除法
除法一开始有点不知所措,上网找的模板参考了才知道除法也分很多种,先说一下小数点后高度精确的吧
#include<stdio.h>
int main()
{
int x,y,n,w;
scanf("%d%d%d",&x,&y,&n);/*输入2个数x,y,精确到小数点后n位*/
printf("%d.",x/y);/*先输出整数的部分*/
x=x%y;
while(n>0)
{
x=x*10; /*这里就像小学生除法一样*/
w=x/y;
printf("%d",w);
if(x==0)
break;
x=x-w*y;
n--;
}
}