大数阶乘

本文介绍了一种高效计算大数阶乘的方法,利用两个整型数组分别存储结果和进位,通过逐步累乘的方式避免溢出问题。适用于解决笔试和面试中的大数运算挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在笔试,面试中经常会碰到大数的操作问题,用基本的数据类型都有溢出的风险。在此,介绍一种比较好的思路,来计算大数的阶乘,比如。100!

首先,定义两个整型的数组:
int fac[1000];//暂且先设定是1000位,我称之为“结果数组”
int add[1000];//我称之为“进位数组”

现在具体说明两个数组的作用:

1.fac[1000]
比如说,一个数5的阶乘是120,那么我就用这个数组存储它:
fac[0]=0
fac[1]=2
fac[2]=1
现在明白了数组fac的作用了吧。用这样的数组我们可以放阶乘后结果是1000位的数。

2.在介绍add[1000]之前,我介绍一下算法的思想,就以6!为例:
从上面我们知道了5!是怎样存储的。
就在5!的基础上来计算6!,演示如下:

fac[0]=fac[0]*6=0
fac[1]=fac[1]*6=12
fac[2]=fac[2]*6=6

3.现在就用到了我们的:“进位数组”add[1000].
先得说明一下:add[i]就是在第2步中用算出的结果中,第i位向第i+1位的进位数值。还是接上例:
add[0]=0;
add[1]=1;  // 计算过程:就是 (fac[1]+add[0])  /  10=1
add[2]=0;  // 计算过程:就是 (fac[2]+add[1]) /10=0
.......
.......
.......

add[i+1] =( fac[i+1] + add[i] ) / 10

现在就知道了我们的数组add[]是干什么的了吧,并且明白了add[i]是如何求得的了吧。



4.知道了add[1000]的值,现在就在 1. 和 3 . 两步的基础上来计算最终的结果。(第2步仅作为我们理解的步骤,我们下面的计算已经包含了它)

fac[0] = ( fac[0]*6 )  mod 10 =0
fac[1] = ( fac[1]*6 + add[0] ) mod 10 =2
fac[2] = ( fac[2]*6 + add[1] ) mod 10=7

到这里我们已经计算完了6!。然后就可以将数组fac[1000]中的数,以字符的形式按位输出到屏幕上了。

5.还有一点需要说明,就是我们需要一个变量来记录fac[1000]中实际用到了几位,比如5!用了前3位;
我们在这里定义为 top
     为了计算top,我们有用到了add[1000],还是以上面的为例:
   
     5!时,top=3,在此基础上我们来看6!时top=?
     由于  add[2]=0
     所以  top=3(没有变)
也就是说,如果最高位有进位时,我们的top=top+1,否则,top值不变。

6.总结一下,可以发现,我们把阶乘转化为 两个10以内的数的乘法,还有两个10以内的数的家法了。
  因此,不管再大的数,基本上都能算出了,只要你的数组够大就行了。

程序实现:

#include "stdafx.h"
#include <iostream>

using namespace std;

#define  MAX 1000

int fac[MAX]={1,};
int add[MAX]={0,};

int top=1;//计算结果位数

void calculate(int n);

void print();

int main(int argc, char * argv[])

cout<<"please input the number:";
int n;
cin>>n;
calculate(n);
cout<<n<<"!=";
print();
cout<<"总共"<<top<<"位"<<endl;
return 0;
}

//计算N的阶乘
void calculate(int n){

if (n<=0)
{
 exit(1);
}

for (int i=1;i<=n;i++)
{
 int m=top;

 for (int j=0;j<m;j++)
 {
    int tmp=fac[j]*i;

             if (j==0)
    {
      fac[0]=tmp%10;
      add[0]=tmp/10;
    }

   else
   {
      fac[j]=(tmp+add[j-1])%10;
      add[j]=(tmp+add[j-1])/10;
    }

    /**最高位有进位
    **连续进位的问题
    */

   while (add[top-1]>0){
     top++;
     int tmp=fac[top-1];
     fac[top-1]=(tmp+add[top-2])%10;
    add[top-1]=(tmp+add[top-2])/10; 
    }
   }
  }
}

//打印输出结果
void print(){
  int j=0;
  for(int i=top-1;i>=0;i--)
  {
   if ((j++)%20==0)
   {
    cout<<endl;
   }
   cout<<fac[i];
   }
    cout<<endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值