C++大数问题

感谢原博主: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百练上的比较基础的例题,从基础的开始做,只要弄懂就好,积累自己的模板,再灵活运用;


2981:大整数加法   http://bailian.openjudge.cn/practice/2981


其实大整数的加法之类的,算法都比较简单,按照我们平时竖式计算的方式,用数组模拟大数的加法,要注意的就是处理好之间的进位问题,然后其中的输入输出也要注意,转化成我们习惯的那种方式去进行计算,输出的时候要处理好前端零;
主要是要理解这种处理方式;
下面是代码:代码就是随便写一下的,还可以进行优化,并不是最简的,能够易于理解就好;
[cpp]  view plain  copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. char a[220],b[220];  
  4. int c[220],d[220];  
  5. int result[240];  
  6. int main()  
  7. {  
  8.     int i=0,j=0,lena,lenb,n;  
  9.     gets(a);//把数字用字符串保存输入  
  10.     gets(b);  
  11.     memset(c,0,sizeof(c));//对数组进行初始化  
  12.     memset(d,0,sizeof(d));  
  13.     memset(result,0,sizeof(result));  
  14.     lena=strlen(a);  
  15.     lenb=strlen(b);  
  16.     n=lena>lenb?lena:lenb;  
  17.     for(j=0,i=lena-1;i>=0;i--)//把字符数组倒序转换到数字数组中(满足我们的计算习惯)  
  18.         c[j++]=a[i]-'0';  
  19.     for(j=0,i=lenb-1;i>=0;i--)  
  20.         d[j++]=b[i]-'0';  
  21.     for(i=0;i<n;i++)  
  22.     {  
  23.      result[i]+=c[i]+d[i];//把两个数组相加  
  24.       if(result[i]>=10)//处理进位  
  25.        {  
  26.            result[i+1]++;  
  27.            result[i]-=10;  
  28.        }  
  29.     }  
  30.     i=n;  
  31.     int flag=0;  
  32.     while(!result[i])//处理前端零  
  33.     {  
  34.         if(i==0)  
  35.         {  
  36.             flag=1;  
  37.             printf("0");  
  38.         }  
  39.         i--;  
  40.     }  
  41.     while(i>=0&&flag==0)  
  42.     {  
  43.         printf("%d",result[i]);  
  44.         i--;  
  45.     }  
  46.     printf("\n");  
  47.     return 0;  
  48. }  

2980:大整数乘法  http://bailian.openjudge.cn/practice/2980


乘法和加法的思想基本上一致,这里要注意的是,i和j位置相乘的结果要保存在结果数组的i+j的位置;
下面是代码;
[cpp]  view plain  copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. char a[220],b[220];  
  4. int c[220],d[220];  
  5. int result[440];  
  6. int main()  
  7. {  
  8.     int i=0,j=0,lena,lenb,n;  
  9.     gets(a);//把数字用字符串保存输入  
  10.     gets(b);  
  11.     memset(c,0,sizeof(c));//对数组进行初始化  
  12.     memset(d,0,sizeof(d));  
  13.     memset(result,0,sizeof(result));  
  14.     lena=strlen(a);  
  15.     lenb=strlen(b);  
  16.     n=lena>lenb?lena:lenb;  
  17.     for(j=0,i=lena-1;i>=0;i--)//把字符数组倒序转换到数字数组中(满足我们的计算习惯)  
  18.         c[j++]=a[i]-'0';  
  19.     for(j=0,i=lenb-1;i>=0;i--)  
  20.         d[j++]=b[i]-'0';  
  21.     for(i=0;i<lena;i++)  
  22.         for(j=0;j<lenb;j++)  
  23.         result[i+j]+=c[i]*d[j];//i*j的结果要保存在i+j的位置  
  24.     for(i=0;i<n*2;i++)  
  25.     {  
  26.         if(result[i]>=10)//处理进位  
  27.         {  
  28.             result[i+1]+=result[i]/10;  
  29.             result[i]%=10;  
  30.         }  
  31.     }  
  32.     i=n*2-1;  
  33.     while(result[i]==0) i--; //处理前端零  
  34.     while(i>=0)  
  35.     {  
  36.          printf("%d",result[i]);  
  37.          i--;  
  38.     }  
  39.     return 0;  
  40. }  

2736:大整数减法   http://bailian.openjudge.cn/practice/2736


减法和加法的思想基本一致;把程序中的加法换成减法,进位处理的时候注意;
下面是代码;
[cpp]  view plain  copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. int main()  
  4. {  
  5.     //freopen("1.txt","r",stdin);  
  6.     char a[220],b[220];  
  7.     int c[220],d[220];  
  8.     int result[240];  
  9.     int n,i,j,lena,lenb;  
  10.     scanf("%d",&n);  
  11.     while(n--)  
  12.     {  
  13.         scanf("\n%s",a);  
  14.         getchar();  
  15.         scanf("%s",b);  
  16.         memset(c,0,sizeof(c));  
  17.         memset(d,0,sizeof(d));  
  18.         memset(result,0,sizeof(result));  
  19.         lena=strlen(a);  
  20.         lenb=strlen(b);  
  21.         for(i=lena-1,j=0;i>=0;i--)  
  22.            c[j++]=a[i]-'0';  
  23.         for(i=lenb-1,j=0;i>=0;i--)  
  24.            d[j++]=b[i]-'0';  
  25.         for(i=0;i<lena;i++)  
  26.             result[i]=c[i]-d[i];  
  27.         for(i=0;i<lena;i++)  
  28.             if(result[i]<0)//处理小于零的情况  
  29.             {  
  30.                 result[i]+=10;//向前一位借10;  
  31.                 result[i+1]--;  
  32.             }  
  33.       for(i=lena-1;!result[i]&&i>0;i--);//处理前端零  
  34.       for(j=i;j>=0;j--)  
  35.        printf("%d",result[j]);  
  36.       printf("\n");  
  37.     }  
  38.     return 0;  
  39. }  

大数阶乘这里就相当于进行了多次乘法,这里我是用的10000进位,基本思想也是一样的;
下面是代码:
[cpp]  view plain  copy
  1. #include <cstdio>  
  2. #include <cmath>  
  3. void factorial(int n)  
  4. {  
  5. int a[10000];  
  6. int i,j,c,m=0;  
  7. a[0]=1;  
  8. for(i=1;i<=n;i++)  
  9. {  
  10.     c=0;  
  11.     for(j=0;j<=m;j++)//m表示的是当前数组的位数  
  12.     {  
  13.         a[j]=a[j]*i+c;  
  14.         c=a[j]/10000;//判断有没有进位  
  15.         a[j]=a[j]%10000; //保存进位的数  
  16.     }  
  17.     if(c>0) {m++;a[m]=c;}  
  18. }  
  19.    printf("%d",a[m]);  
  20.    int w=m*4+log10(a[m])+1;//这里是计算阶乘的总位数 (这里可以不要)  
  21.    for(i=m-1;i>=0;i--)  
  22.       printf("%0.4d",a[i]);//假如当前位置的数没满4位的话,在前补零  
  23.     printf("\n");  
  24.     printf("%d",w);//(也可以不要这个输出)  
  25. }  
  26. int main()  
  27. {  
  28.     int m;  
  29.     while(scanf("%d",&m)!=EOF)  
  30.     {  
  31.         factorial(m);  
  32.     }  
  33.     return 0;  
  34. }  

大数除法还要自己去研究一下~研究好了再更新~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值