感谢原博主:http://blog.csdn.net/whjkm/article/details/38148893
今天给学弟学妹们讲大数问题,自己又把大数问题好好的复习了一遍,用c重新实现了一下;除法还是有点复杂,有点没搞清,所以就不误人子弟了,把大数的加法,乘法,减法,阶乘都自己写了一遍,对大数问题又加深了一点,大精度的还是要慢慢的积累,Java版本的上次已经写了;加一个自己的传送门;java写真的是挺方便的啊;java大数
一些基本数据类型的范围:
int:32位整数,占4字节,-2^31~2^31-1(-21亿多~21亿多)
unsigned int:占4字节,0~2^32-1(0~42亿多) –10位数
VC的64位整数 :
__int64:占8字节,-2^63~2^63-1(-900亿亿多~900亿亿多)
unsigned __int64:占8字节,0~2^64-1(0~1800亿亿多)-20位数
G++的64位整数:
long long==__int64
unsigned long long==unsigned __int64
实数
float:占4字节,7位有效数字
double:占8字节,15位有效数字
浮点型的问题都是追求精度的,在一般情况下我们应当选择使用double,而很少用float;
所以当我们要进行计算的数超过了20位,我们就要用数组来模拟我们的计算过程了;
选取的是poj百练上的比较基础的例题,从基础的开始做,只要弄懂就好,积累自己的模板,再灵活运用;
其实大整数的加法之类的,算法都比较简单,按照我们平时竖式计算的方式,用数组模拟大数的加法,要注意的就是处理好之间的进位问题,然后其中的输入输出也要注意,转化成我们习惯的那种方式去进行计算,输出的时候要处理好前端零;
主要是要理解这种处理方式;
下面是代码:代码就是随便写一下的,还可以进行优化,并不是最简的,能够易于理解就好;
- #include <cstdio>
- #include <cstring>
- char a[220],b[220];
- int c[220],d[220];
- int result[240];
- int main()
- {
- int i=0,j=0,lena,lenb,n;
- gets(a);
- gets(b);
- memset(c,0,sizeof(c));
- memset(d,0,sizeof(d));
- memset(result,0,sizeof(result));
- lena=strlen(a);
- lenb=strlen(b);
- n=lena>lenb?lena:lenb;
- for(j=0,i=lena-1;i>=0;i--)
- c[j++]=a[i]-'0';
- for(j=0,i=lenb-1;i>=0;i--)
- d[j++]=b[i]-'0';
- for(i=0;i<n;i++)
- {
- result[i]+=c[i]+d[i];
- if(result[i]>=10)
- {
- result[i+1]++;
- result[i]-=10;
- }
- }
- i=n;
- int flag=0;
- while(!result[i])
- {
- if(i==0)
- {
- flag=1;
- printf("0");
- }
- i--;
- }
- while(i>=0&&flag==0)
- {
- printf("%d",result[i]);
- i--;
- }
- printf("\n");
- return 0;
- }
乘法和加法的思想基本上一致,这里要注意的是,i和j位置相乘的结果要保存在结果数组的i+j的位置;
下面是代码;
- #include <cstdio>
- #include <cstring>
- char a[220],b[220];
- int c[220],d[220];
- int result[440];
- int main()
- {
- int i=0,j=0,lena,lenb,n;
- gets(a);
- gets(b);
- memset(c,0,sizeof(c));
- memset(d,0,sizeof(d));
- memset(result,0,sizeof(result));
- lena=strlen(a);
- lenb=strlen(b);
- n=lena>lenb?lena:lenb;
- for(j=0,i=lena-1;i>=0;i--)
- c[j++]=a[i]-'0';
- for(j=0,i=lenb-1;i>=0;i--)
- d[j++]=b[i]-'0';
- for(i=0;i<lena;i++)
- for(j=0;j<lenb;j++)
- result[i+j]+=c[i]*d[j];
- for(i=0;i<n*2;i++)
- {
- if(result[i]>=10)
- {
- result[i+1]+=result[i]/10;
- result[i]%=10;
- }
- }
- i=n*2-1;
- while(result[i]==0) i--;
- while(i>=0)
- {
- printf("%d",result[i]);
- i--;
- }
- return 0;
- }
减法和加法的思想基本一致;把程序中的加法换成减法,进位处理的时候注意;
下面是代码;
- #include <cstdio>
- #include <cstring>
- int main()
- {
-
- char a[220],b[220];
- int c[220],d[220];
- int result[240];
- int n,i,j,lena,lenb;
- scanf("%d",&n);
- while(n--)
- {
- scanf("\n%s",a);
- getchar();
- scanf("%s",b);
- memset(c,0,sizeof(c));
- memset(d,0,sizeof(d));
- memset(result,0,sizeof(result));
- lena=strlen(a);
- lenb=strlen(b);
- for(i=lena-1,j=0;i>=0;i--)
- c[j++]=a[i]-'0';
- for(i=lenb-1,j=0;i>=0;i--)
- d[j++]=b[i]-'0';
- for(i=0;i<lena;i++)
- result[i]=c[i]-d[i];
- for(i=0;i<lena;i++)
- if(result[i]<0)
- {
- result[i]+=10;
- result[i+1]--;
- }
- for(i=lena-1;!result[i]&&i>0;i--);
- for(j=i;j>=0;j--)
- printf("%d",result[j]);
- printf("\n");
- }
- return 0;
- }
大数阶乘这里就相当于进行了多次乘法,这里我是用的10000进位,基本思想也是一样的;
下面是代码:
- #include <cstdio>
- #include <cmath>
- void factorial(int n)
- {
- int a[10000];
- int i,j,c,m=0;
- a[0]=1;
- for(i=1;i<=n;i++)
- {
- c=0;
- for(j=0;j<=m;j++)
- {
- a[j]=a[j]*i+c;
- c=a[j]/10000;
- a[j]=a[j]%10000;
- }
- if(c>0) {m++;a[m]=c;}
- }
- printf("%d",a[m]);
- int w=m*4+log10(a[m])+1;
- for(i=m-1;i>=0;i--)
- printf("%0.4d",a[i]);
- printf("\n");
- printf("%d",w);
- }
- int main()
- {
- int m;
- while(scanf("%d",&m)!=EOF)
- {
- factorial(m);
- }
- return 0;
- }
大数除法还要自己去研究一下~研究好了再更新~