也谈大数阶乘

最近公司里面的项目一直用c++来进行,基础太薄弱,于是自己完成了公司的任务后,加紧练习。

本来那天是想写一个递归阶乘算法的,发现有不少问题啊:

第一: 递归有一个弊端,就是栈空间不够的问题

第二:遇到大数的时候,在cpp中没有办法找到合适的数据类型来进行计算,用long,double都是不可能够的。因为我一开始的目标至少是要计算到1000的阶乘的(现在想想实在太小)。

下面简单说说实现的思路:

n!,对于任意的0<m<n, 假设计算结果为result,因为result的位数>=n的位数。所以就对每一个result对n进行相乘计算,然后再相加。

 

1)初始分配空间

假设定义 long* result = (long*)malloc(sizeof(long*n*Q);其中的Q我为了考虑足够的空间,暂时取的是10(这个q的计算我尚未进行,所以在空间上是有浪费的)。用malloc来定义result,是考虑到大数的结果位数比较大,需要存放的空间会比较大,所以放在堆中(题外,对于堆栈存储的理解也不知道对不对,最近公司里面要我写的代码中有一段用了递归,于是公司的同事告诉我,递归可能会导致栈空间不够,最好不要用递归,于是自己上网查了查,大概就这么理解。不知道堆中最多能存放多少的空间呢?是不是内存有多少就能存多少?)。

 

2)核心算法

     for i: 1-n      //从1*2*3*4...n

     {  

        int upvalue = 0;

        for j: 0-result.size  //  假设result是712,那么result[0]=2,result[1]=1,result[2]=7.然后计算下一个result的时候,分别

                                          // 每一位对i相乘,如果>10,再进位

        {

              int tmpvalue = resultM[j] * i + upvalue;   //将result当前位和i相乘后+进位,计算结果放在临时变量tmpvalue中
              resultM[j] = tmpvalue % 10;                    //当前位存放tmpvalue的个位数
              upvalue = tmpvalue / 10;                        // 将tmpvalue/10后的数用于存放进位,供下次计算使用

        }

         //当result计算完成结束循环后,如果最后一位有进位,那么result的位数就要增加,所以这里就要对这个情况进行处理

        while(upvalue != 0)
        {
          resultM[size] = upvalue % 10;
          upvalue /= 10;
          size++;
         }

     }

     如此就算完成了。

3)改进

    查看结果可以发现,后面有若干个0.如果在for j: 0-result.size  这层循环里面进行数个0*i,就很浪费时间了。

    所以在for j: 0-result.size  循环前,判断0的个数,初始zeroNumber=-1:

   while(result[zeroNumber + 1] == 0)
   {
   zeroNumber++;
   }

    然后将for j: 0-result.size  中,j的初始计算改为zeroNumber+1,这样效率就会提高不少。

4)源码

       

5)效果

    我在公司的机器稍微好些,10000基本秒杀,100000基本在2分钟左右计算完成。

    我在家的机器配置稍差,我在虚拟机中运行,1.96G cpu,256M内存,计算10000在5秒内,计算100000需要14分钟以内

6)不足

    CPU占用率高,不知道编程的时候,有哪些会使得cpu占用率高?要怎么使cpu占用率降低呢?

    内存空间还存在有浪费情况。

    效率还不够高。

7)小结

    对大数阶乘的学习暂时告一段落了,等以后学的知识再多些,才能再进行改进了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值