数论-大数阶乘

大数阶乘

为了考虑精度问题,所以大数阶乘需要一个算法

首先来看,100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
所以一个 64位的 long long 型,数据存不下,所以需要考虑新的思路,利用数组来存储位数。

考虑,一个位数上为 6 ,乘上8 ,得到进位十位为 4,个位为 8,就让8存储在当前位,4就存储在下一位(数组中的数是从前往后存储的)。

在考虑一下,数组可以开的大小在 105-106左右,所以能存储的最大位为 106,所以在考虑一下,能不能让数组中的每个数的位数都用。就可以每一位存储10的4次方,像1111*2222 = 2468642,进位数为246,余数为8642,2222再乘上8642 又有进位数和余数实现数的存储。
这样利用数的存储空间int型4位可以用109 或者 long long 型8位可以用1018,就会大于使用char型数组1字节1位,就会最大的利用空间。

注意:单独输出 a[num] 表示的意思是最后一次计算后得到的值 t 没有取模,所以可能会大于maxn的数。

大致就是这个过程,可以参考代码:

#include<stdio.h>
#include<math.h>
int maxn_s(int n){
	int cnt = 0;
	while(n){
		n /= 10;
		cnt++;
	}
	return cnt;
}
int factorial(int n){	//返回值为数的位的个数 
	const int maxn = 10000;		//表示数组中一个数存最大的位数 
	const int s = maxn_s(maxn)-1;		//表示maxn的位数函数 
	printf("数组a中每一位存储的数据范围为%d个9",s);
	int a[maxn] = {1};	//数组初始化,除了a[0] = 1外,其他的数默认赋值为0
	int t,num = 0;
	for(int i = 1;i <= n;i++)	//表示1-n每一个都乘一遍 
	{
		t = 0;	//t表示进位的数
		for(int j = 0;j <= num;j++){
			a[j] = a[j]*i + t;
			t = a[j]/maxn;		//表示进的位
			a[j] = a[j]%maxn;		//表示除了进位的剩下来的数
		}
		if(t > 0) {num++;a[num] = t;}	//如果每一次乘法后,最大的一位是否会超过边界,超过就会让数组第一位存下超过的数 
	}
	int length = num*s + log10(a[num]) + 1;
	printf("\n%ld",a[num]);
	for(int i = num-1;i >= 0;i--) printf("%4.4d",a[i]);	//详细看最下面解释
	return length;
}
int main()
{
	int n;		//n的阶乘 
	scanf("%d",&n);
	int s = factorial(n);
	printf("\n字符的长度%d",s);
	return 0;
}

解释一下:lenght 表示这个数的长度,s表示数组中每一个数存几位,num * s + log10(a[num]) + 1 中,num*s 表示除一个数最前面num位上的数,剩下的位数,而log10(a[num]) 表示最后一位数可能会很大,所以就要用 log10(a[num]) 来表示(例 log10111 强制类型转化后得到的只是 2,但是 111有3位,所以最后面又加了一个 1)所以具体就是这样。

%4.4d中,
4的意思表示留4位的空间
.4表示保留4位数
1)超4位的数删掉(这里不用这一条)。
2)小于4位就补 0。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值