大数 斐波那契 与阶乘

来源:互联网 发布:安知玉如意百度云 编辑:程序博客网 时间:2024/05/18 02:36

此代码 之所以能得到1--40000的斐波那契数 主要是内存用得少 循环加法 当然 如果要得到 100万  要改改size 另外求解的时间也要增加我试了试  用这个 得到 第40万个数 需要 大约1分钟     只要是 前 10万都很快  # include <stdlib.h># include <stdio.h># define M 1000000000/*每一个int存9位*/# define size 9290/*第40万个斐波那契需要9290个int的存储空间*/# define MAX 400000int add(int a[][size],int d);void main(){int shu[3][size]={0,0,0},num,wei=0,k;/*初始化shu[][];*/while(wei<1||wei>MAX){printf("显示第几个斐波纳挈数?(1--%d):\n",MAX);scanf("%d",&wei);while(getchar()!='\n');}k=num=add(shu,wei);wei=(wei-1)%3;    printf("%d",shu[wei][num--]);while(num>0)printf("%09d",shu[wei][num--]);  printf("\n比%d多(0--9)位%d",(k-1)*9,shu[wei][1]%10007);  getchar();}int add(int a[][size],int b){int i,j,m,k,c[]={0,1,2},index=1;a[0][1]=a[1][1]=1;/*初值为1  1*/for (i=1;i<=b;i++){for (j=1;j<=index; j++)a[c[2]][j]=a[c[0]][j]+a[c[1]][j];for (k=1;k<index; k++)if (a[c[2]][k]>=M) {a[c[2]][k+1]+=a[c[2]][k]/M;  /* 当前位向前进位 */a[c[2]][k]%=M;             /*当前位进位之后的值 */} while (a[c[2]][index] >= M&& index <= size-1){a[c[2]][index+1] = a[c[2]][index]/M;  /* 向最高位进位 */a[c[2]][index++]%=M;    /* 进位之后的值,位数+1*/}for(m=0;m<3;m++)c[m]=(c[m]+1)%3;//对c[0--2]循环做加法} return index;}

阶乘:

大数字阶乘    int 与unsigned __int64类型存储方式与计算速度的比较大数字阶乘已经是老掉牙的东西了,有 斯特林快速求解阶乘的近似公式  还有利用double求精准位数的高手……,不过今天要说的是求精确值的算法,在开始学阶乘的运算时大概都是递归开始 递归慢不如迭代法  之后又用char存储,每个存一位。但是当数字达到20000时发现慢的要死;之后又改为int 存储,一个int存一位,速度快了一点,但是内存浪费严重 如果求30000的阶乘要开辟121288个int的空间相当于 121288*4个字节 如果再高点 如果40000  那么 内存太大 虽然编译没问题 但是程序一运行就挂了  之后又改为一个int存4位  速度更快了 内存也降下来了 求30000的阶乘需要30322个int空间 ,但是我还想更快  更节省内存 不由的想到了把 int改为 __int64 或者unsigned __int64 在测试中我放弃了__int64因为它虽然比int快但不如unsigned __int64快。之后测试 确定了 一个 unsigned __int64 存14位那么 结果如何呢?速度更快了。这个快不仅体现在运算上,还体现在输出时间上。下面是int和unsigned __int64的代码://int   一个int存4位#include <stdio.h>#define  SIZE  77200   //30000!有121288位,但是每四位进一位,所以即使是40000!也只用到41279位,50000!  53310*4位左右# define N 10000   /*10000不要改效率更快*/       //60000! 65195*4位左右  7000!  77920左右int BigFact(int m, int data[]);//计算m的阶乘void main(){int data[SIZE] = {0};         /*存储SIZE位数,元素全部初始化为0,data[0]空着 */int index,j,n=0;              /* 数组元素个数,表示阶乘值的位数 */    while(n<1||n>70000)    {printf("输入n int 求n!4 (1-70000)注:\n10000!用时约2秒\n20000!用时约5秒\n30000!用时约11秒\n40000!用时约21秒\n50000!用时约37秒\n60000!用时约52秒\n70000!用时约73秒\n");scanf("%d", &n);while(getchar()!='\n');}printf("%d!=\n", n);n=index = BigFact(n,data);/* 计算阶乘n!,返回阶乘值的位数 */if (index)     /* 检验数组是否溢出,若未溢出,则打印阶乘值 */printf("%d",data[index--]);while(index>0)printf("%04d",data[index--]);printf("\n位数大约为%d±4位\n ",n*4);getchar();}/*函数功能:计算m!,存于数组data中,若数组未溢出,则返回阶乘值的位数,否则返回0*/int BigFact(int m, int data[]){    int i, j, k;int index = 1;         /* 数组元素个数,表示阶乘值的位数 */data[1] = 1;           /* 初始化,令1!=1 */for (i=1; i<=m; i++)  /* 计算阶乘m!*/{for (j=1; j<=index; j++)data[j]=data[j] * i;/*每一位数字都乘以i,模仿乘法计算*/for (k=1;k<index; k++)if (data[k]>=N)   /*阶乘值的每位数字应在0~9之内若>=10,则进位*/{data[k+1]+=data[k]/N;  /* 当前位向前进位 */data[k]%=N;/*当前位进位之后的值 */}/* 单独处理最高位,若计算之后的最高位>=10,则位数index加1 */while (data[index] >=N && index <= SIZE-1){data[index+1] = data[index]/N;  /* 向最高位进位 */data[index]%=N;    /* 进位之后的值 */index++;                                /* 位数index加1 */}}return index <= SIZE-1?index:0;/* 检验数组是否溢出,若未溢出,则返回阶乘值的位数 */}接下来为unsigned __int64 #include <stdio.h>#define  SIZE  22056  typedef unsigned __int64 elem;const unsigned __int64 N=100000000000000;//一个elem存14位int BigFact(elem m,elem data[]);//计算m的阶乘void main(){elem data[SIZE] = {0};         /*存储SIZE位数,元素全部初始化为0,data[0]空着 */int index,n=0;              /* 数组元素个数,表示阶乘值的位数 */    while(n<1||n>70000)    {printf("输入n求n!14位 unsigned __int64(1-70000)注:\n10000!用时约1秒\n20000!用时约5秒\n30000!用时约11秒\n40000!用时约21秒\n50000!用时约34秒\n60000!用时约50秒\n70000!用时约70秒\n");scanf("%I64u", &n);while(getchar()!='\n');}printf("%I64u!=\n", n);n=index = BigFact(n,data);/* 计算阶乘n!,返回阶乘值的位数 */if (index)     /* 检验数组是否溢出,若未溢出,则打印阶乘值 */printf("%I64u",data[index--]);while(index>0)printf("%014I64u",data[index--]);printf("\n位数大约为%d±14位 占用空间%d个unsigned__int64\n ",n*14,n);getchar();}/*函数功能:计算m!,存于数组data中,若数组未溢出,则返回阶乘值的位数,否则返回0*/int BigFact(elem m,elem data[]){    int i, j, k;int index = 1;         /* 数组元素个数,表示阶乘值的位数 */data[1] = 1;           /* 初始化,令1!=1 */for (i=1; i<=m; i++)  /* 计算阶乘m!*/{for (j=1; j<=index; j++)data[j]=data[j] * i;/*每一位数字都乘以i,模仿乘法计算*/for (k=1;k<index; k++)if (data[k]>=N)   /*阶乘值的每位数字应在0~9之内若>=10,则进位*/{data[k+1]+=data[k]/N;  /* 当前位向前进位 */data[k]%=N;/*当前位进位之后的值 */}/* 单独处理最高位,若计算之后的最高位>=10,则位数index加1 */while (data[index] >=N && index <= SIZE-1){data[index+1] = data[index]/N;  /* 向最高位进位 */data[index++]%=N;    /* 进位之后的值 位数index加1 */}}return index <= SIZE-1?index:0;/* 检验数组是否溢出,若未溢出,则返回阶乘值的位数 */}比较一下    : 阶乘!      时间(秒): int          unsigned __int6410000        2                                   1             20000        5                                   4.530000       11                                  10.540000       21                                   2050000       37                                   3460000       52                                    4970000       73                                   70输出速度因为unsigned __int64是以%014I64d输出一次14位  而 int   是%04d 输出一次4位   明显int输出慢   


3 0