优化阶乘算法的探索

优化阶乘算法的探索优化阶乘算法的探索中国地质大学(武汉)  陈海丰 阶乘(factorial)是基斯顿·卡曼(ChristianKramp,1760–1826)于1808年发明的运算符号。阶乘,也是数学里的一种术语,是指从1乘以2乘以3乘以4一直乘到所要求的数。例如所要求的数是4,则阶乘式是1×2×3×4,得到的积是24,24就是4的阶乘。如果所要求的数是n,则阶乘式是1×2×3×……×n,设

大家好,又见面了,我是你们的朋友全栈君。

优化阶乘算法的探索

中国地质大学(武汉)   陈海丰

 

阶乘(factorial)是基斯顿·卡曼(Christian Kramp, 1760 – 1826)于1808年发明的运算符号。阶乘,也是数学里的一种术语,是指从1乘以2乘以3乘以4一直乘到所要求的数。例如所要求的数是4,则阶乘式是1×2×3×4,得到的积是24,24就是4的阶乘。如果所要求的数是n,则阶乘式是1×2×3×……×n,设得到的积是x,x就是n的阶乘。在表示阶乘时,就使用“!”来表示,如n阶乘,就表示为n!。
    根据阶乘的定义,我们不难得到求解阶乘的递推式。

            …………………………………(1)

当n值很小时,在计算机中可以直接用整型数据的运算就可以解决了,可是当n值很大,比如n=10000时计算结果就不能用现有的数据类型来存放了,因为它的位数已远远超过了现有的数据类型(如10000!有35660位)。为了解决所有数据类型都无法存放这样一个庞大的数据,目前大家采用的是将一个大数一位一位的存放到一个字符型数组或整型数组中,然后要运算时对其每一位进行单独运算,这样就解决了庞大数据的存放问题。但具体怎样对两个都比较大的数的作乘法运算呢?这就要利用大整数的高精度运算。如A,B都是位数比较多的大整数,现在要作A*B运算。小学时我们作45*12是先把12中的2与45的个位5相乘,再把2与45的十位4相乘,然后同样再把12中的1与45中的每一位从低到高依次相乘。在这里我们也可以模拟45*12,把A中每一位从低到高与B中的个位相乘,与后再与B中的十位相乘,依次类推,最后把所有的结果对应相加就可以得到所要求的结果了。

具体代码(一):

#include <stdio.h>

#include <string.h>

 

char a[40000], b[10];

int c[40000];

int main()

{    

    int n;

     while(scanf(“%d”, &n) != EOF){

        int la, lb, lc, i, j, k, k1;

        if(n == 0 || n == 1){

              printf(“1/n”);

              continue;

         } //几种特殊情况

        if(n == 2){

              printf(“2/n”);

              continue;

         }

        a[0] = 50;   //初始化使是最先相乘的数从开始

         for(k1 = 3;k1 <= n;k1++){                  

              k = k1;          

              for(j = 0;k;j++){

                   b[j] = k % 10 + 48;

                   k /= 10;

              }          

              la = strlen(a);

              lb = strlen(b);  

              memset(c, 0, sizeof(c));      

              for(i = 0;i < la;i++){

                   for(j = 0;j < lb;j++){          

                       c[i + j] += (a[i] – 48) * (b[j] – 48);

                       //循环相乘,结果存放到另一数组中         

                       c[i + j + 1] += c[i + j] / 10;   //进位         

                       c[i + j] %= 10;

                       lc = i + j + 1;   //当前位     

                   }

              }

              if(c[lc] == 0) lc–;    

              for(i = lc;i >= 0;i–)

                   for(i = lc;i >= 0;i–) a[i] = c[i] + 48;

                   //将结果复制到数组a中,再和b数组相乘

         }

         for(i = lc;i >= 0;i–){   //输出结果时从数组的最后一个开始输出

              printf(“%c”, a[i]);

        }

         printf(“/n”);    

         memset(a, 0, sizeof(a)); //将数组全部初始化

         memset(b, 0, sizeof(b));        

     }

     return 0;

}

上面程序可以计算大数的阶乘,但是效率非常的低,如10000!的阶乘需要2000Ms左右,所以这种算法并不能解决实际问题。考虑到上面的程序是一位一位的把一个大数存放下来,然后相乘时也是一位一位的进行的。然后我想到定义一个整型的数组,每一位不是存放一位而是存放五位,这样相加,相乘的次数就是原来的 ,10000!运算时间是200Ms,是原来的 。

具体代码(二):

 

#include<stdio.h>

 

int main()  

{    

     int n;

     printf(“请输入一个整数N(0~20000):/n”);    

     while(scanf(“%d”, &n) != EOF){      

         int s[16000] = {0}, j, i, k = 0, t = 0, p = 0;

         long sum = 0;        

         s[0] = 1;  

         for(j = 1;j <= n;j++){  

              for(i = 0;i <= t;i++){  

                   sum = s[i] * j + p;  

                   p = 0;  

                   if(sum > 99999){  

                       s[i] = sum % 100000;   //每一位存放位         

                       p = sum / 100000;          

                       if(t == i){

                            t++;

                            s[t] = 0;

                       }  

                   }  

                   else s[i]=sum;  

              }  

         }  

         printf(“%d!=”, n);

         printf(“%d”, s[t]);  

         for(i = t – 1;i >= 0;i–){    

              printf(“%05d”,s[i]);  

         }  

         printf(“/n/n”);

         printf(“请再输入一个整数N(0~20000):/n”);

     }  

     return 0;  

}

 

当然在程序中可以把存放大数的数组定义成长整型(long)则每一个数组元素可以存放更多位,10000!的运行时间可以缩短到50Ms。在实践中算法的可行性是非常重要的,算法要不断的优化才能有机实际作用,所以要学会优化算法,提高自己的编程能力。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cschf/archive/2008/05/28/2491623.aspx

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/164010.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 「从零单排canal 03」 canal源码分析大纲

    「从零单排canal 03」 canal源码分析大纲

    2020年11月19日
    216
  • vi 命令 使用方法

    vi 命令 使用方法

    2021年11月14日
    46
  • 2.什么是线程间的通信 ?怎么实现线程通信

    2.什么是线程间的通信 ?怎么实现线程通信2.1什么是线程通信以及实现步骤线程间通信的模型有两种:共享内存和消息传递线程通信其实就是,实现线程的交替工作,并传递信息线程间的通信具体步骤:(涉及上中下部)创建资源类,在资源类中船舰属性和操作方法 在资源类操作方法:判断、操作、通知 创建多个线程,调用资源类的操作方法 防止虚拟唤醒问题(if判读,只会判断一次)2.2synchronized案例操作线程的时候,等待线程使用wait()通知另外的线程操作用notify()、notifyAll()假设…

    2022年7月16日
    17
  • 磁盘在磁盘管理中显示没有初始化找回文件方案「建议收藏」

    磁盘在磁盘管理中显示没有初始化找回文件方案「建议收藏」磁盘没有初始化是因为0号扇区损坏,导致机械硬盘分区表读取不出来,从而机械硬盘出现磁盘没有初始化。工具/软件:极限数据恢复软件步骤1:程序打开后,直接双击需要恢复数据的物理盘。步骤2:等待程序扫描完毕大概需要几分钟到半个小时,稍微耐心等下即可。步骤3:软件扫描到资料后,软件会将扫描到的分区列出来。步骤4:勾上所有需要恢复的资料,右击选择《复制勾选的文件》,…

    2022年9月21日
    0
  • 什么是ER图?数据库ER图基础概念整理

    什么是ER图?数据库ER图基础概念整理前置知识概述:数据模型的基本概念模型就是对现实世界特征的模拟和抽象,数据模型是对现实世界数据特征的抽象。对于具体的模型人们并不陌生,如航模飞机、地图和建筑设计沙盘等都是具体的模型。最常用的数据模型分为概念数据模型和基本数据模型。1)概念数据模型概念数据模型也称为信息模型,是按用户的观点对数据和信息建模,是现实世界到信息世界的第一层抽象,强调其语义表达功能,易于用户理解,是用户和数据库设计人员交流的语言,主要用于数据库设计。这类模型中最著名的是实体联系模型,简称E-R模型。2)基本数据

    2022年6月21日
    39
  • 怎样完全卸载tensorflow?

    怎样完全卸载tensorflow?查看tensorflow版本sudopipshowtensorflow卸载:sudopipuninstallprotobufsudopipuninstalltensorflow安装:sudopipinstall–upgrade

    2022年6月22日
    84

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号