正文

超高精度算阶乘(快速)2007-03-31 00:49:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/yzfy/24430.html

分享到:

//以10进制输出结果,本程序计算1000!用时不到50ms
#include <stdio.h>
#include <conio.h>
#include <time.h>  //用于计时
#define MaxNum        10000  //阶乘最大的数(最高位数)
//如果要算更大的n!请自行修改此值

void LargeNumberTimes(long *num,long &nMax,long nTimes)
{
    long z1,z2,z3=0;
    for(z1=0;z1<=nMax;z1++)
    {
        if((z2=num[z1]*nTimes+z3)>=10000)
        {
            z3=z2/10000,z2%=10000;
            if(z1==nMax)nMax++;
        }
        else z3=0;
        num[z1]=z2;
    }
}

int main()
{//雨中飞燕之作;
    long n,n1,nt,nMax=0,n0=0,n5=0,nc2=-10,nMod5,num[MaxNum]={1};
    scanf("%d",&n);//输入n,求n!
    long t=clock();//开始计时
    for(nMod5=n1=2;n1<=n;n1++,nMod5++)
    {
        if(nMod5==10)n0++,nc2++,nt=n1/10,nMod5=0;else
        if(nMod5==5)
        {
            n0++,nt=n1/5;
            while(nt%5==0 && nt)n0++,nt/=5;
        }
        else nt=n1;
        while(n0>=nc2 && (nt&1)==0 && nt)nc2++,(nt>>=1);
        if(nt>1)LargeNumberTimes(num,nMax,nt);
    }
    if((nc2+=10)>n0)LargeNumberTimes(num,nMax,(1<<(nc2-n0)));
    t=clock()-t;//结束计时
 
    printf("%d",num[nMax]);//输出计算结果
    for(n1=nMax-1;n1>=0;n1--)printf("%04d",num[n1]);
    for(n1=0;n1<n0;n1++)printf("0");printf("\n");
 
    printf("Time = %d ms",t);//输出用时
    getch();return 0;
}

阅读(7505) | 评论(24)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

评论人:踏雪寻梅 发布时间: 2009-01-04 00:08:00
很有兴趣,代码很好,
希望能加点注释,变量的命名,有点要猜谜的感觉
我会常来的,,,,
评论人:菜鸟三岁半 发布时间: 2008-03-05 18:56:00
我想对程序加上足够清晰的注释更有利于他人分析理解,和学习。这只是我的个人建议,希望能够得到采纳。
评论人:eastcowboy 发布时间: 2007-04-24 03:57:00
我以前也写过一个,但代码要长很多。先是估计最终结果的位数并动态分配内存,然后计时,运算中动态显示进度。
计算的思路差不多,大致就是使用一个int的数组来保存临时结果,每一个int保存四位有效数字,如果一个int是32位的话,大约可以计算到20万的阶乘(如果有足够耐心的话)
当时用1.3G的赛扬CPU,Dev-C++,算2万的阶乘需要7.35秒,现在换了新CPU用VS 2005 Release编译则仅要1.6秒,小小的感叹一下。
代码在http://www.programfan.com/team/team.asp?team_id=99,在这下面的某个帖子里。注意看2楼,1楼那个不算~
评论人:liangbch 发布时间: 2007-04-17 17:44:00
  我记错了,4行代码计算10万的阶乘的帖子是发表在csdn,参见:http://topic.csdn.net/t/20001226/11/52263.html
评论人:liangbch 发布时间: 2007-04-17 17:39:00
  我在 http://www.programfan.com/club/showbbs.asp?id=150502的15楼,给出一个计算阶乘的代码,经测试,速度比楼主的略快,但代码比楼主的简洁,计算部分主要是一个二重循环。
评论人:liangbch 发布时间: 2007-04-17 17:24:00
  哈哈!代码写的复杂了一些,我早在2001.1.1的在网易社区的一个回帖中就给出了4行代码计算10万的阶乘程序。如果内存足够多,这个程序可以算到40亿的阶乘。 原帖请参见:http://book.hackbase.com/57/28002.htm

评论人:坏 发布时间: 2007-04-17 13:24:00
代码帖不上去有点长.
我写的1000!比你的快一些噢
10000!在1s之内
评论人:rickone 发布时间: 2007-04-09 11:06:00
加个0,10000!和1000!差十万八千里,不在一个数量级
评论人:雨中飞燕 发布时间: 2007-04-08 13:27:00
那简单啊,让程序重复运行上千次,上万次再测算时间就行了,把时间差扩大也行啊
评论人:浪雪狂杰 发布时间: 2007-04-08 13:23:00
如果测试一些简单的程序用的机子配置要也底也好把,因为精确度到的是ms而机子配置也高,运行的速度就也快,配置过高就更难看出差距?????
还有和操作系统也有关系?????
如果用386去运行这个1000!的程序不知道会怎么样????
评论人:雨中飞燕 发布时间: 2007-04-08 12:32:00
回复楼下,因为clock()函数的精确度不是真正精确到1ms,实际上是十几ms,用WinAPI的GetTickCount会稍精确一些,不过最好是使用高精度时间函数
QueryPerformanceFrequency
QueryPerformanceCounter
评论人:浪雪 发布时间: 2007-04-08 02:14:00
我用你程序中的计时函数到我自己的程序中,
为什么会出现47,63,47,47,47,63的情况啊,就是显示的时间有周期性,测的是同一个程序为什么会出现这个现象用的dec c++编程工具
评论人: 发布时间: 2007-04-03 10:56:00
怎么用文件形式输入和存贮数据和结果呢
我用的是VC++6。0,不好实现啊,编译没错误,可是结果是错的,可以请教吗
评论人:玉1007 发布时间: 2007-04-02 21:28:00
什麼啊,一個簡單的算法寫的那麼難做什麼。
评论人:forjane 发布时间: 2007-04-02 20:47:00
呵呵,楼下不用理会连原程序都看不懂的无聊人士的
除非他/她提出好的算法或改进
评论人:雨中飞燕 发布时间: 2007-04-02 19:08:00
楼下的,什么1000!的阶可以在1S之内求得??
1S=1000ms啊
偶这个算1000!在偶的机子上也不到20ms,20ms是0.02秒
评论人:vcacm 发布时间: 2007-04-02 17:55:00
1000!的阶可以在1S之内求得!
大大姐!
你的程序还不够牛呀!
评论人:雨中飞燕 发布时间: 2007-03-31 12:08:00
呵呵,不减10的话在某些情况下结果会不正确的
当然,可以不减那么多,适可而止就行了,减的太多也会出错的:)
评论人: 发布时间: 2007-03-31 12:03:00
倒。。。
为什么不直接nc2= 0非要减个10...
评论人:雨中飞燕 发布时间: 2007-03-31 11:41:00
因为一开始nc2=-10
评论人: 发布时间: 2007-03-31 09:08:00
还有啊大姐大,有一点不了解的,就是为什么最后面那个nc2要加上10?有什么玄机吗?
评论人:雨中飞燕 发布时间: 2007-03-31 08:51:00
改好了,谢谢你
评论人:雨中飞燕 发布时间: 2007-03-31 08:49:00
完全可以-,-
才发现num[z1]不可能为0......-,-
评论人:大姐大 发布时间: 2007-03-31 08:30:00
if(num[z1])z2=num[z1]*nTimes+z3;else z2=z3;
这一句不能用:
z2=num[z1]*nTimes+z3代替吗?
您需要登录后才能评论,请 登录 或者 注册