大数阶乘?不用大整数函数也可以!!

大家好,我是Ziyang。欢迎大家来到我的博客,希望能和大家多多交流。地址:https://www.cnblogs.com/ziyang1060/

大数阶乘

由于阶乘的结果会呈几何级数增长,即使在如今的64位字长的计算机中,能表示的大小也是有限的,只能保存20的阶乘。
那我们如何求很大的数的阶乘呢?(例如1000!)
这里我们不考虑复杂的大整数函数,而尝试用一种简单的求大数阶乘的办法。

思路:

将多位数相乘化解为一位数相乘,例如:
已知 11! = 39916800
此时,我们想要得出 12!
在这里插入图片描述
当我们将 11! 的每一位数都乘以12后,总的结果就变得十分简单明了。我们只需从最低位开始,依次考虑该位的进位问题,假如说这个位上是96,那么就要往上一位进9,以此类推。

代码如下:

//求大数阶乘 https://blog.csdn.net/Ziyang1060
#include<stdlib.h>
#include<stdio.h>
#include<math.h>

int find_digit(int num);//返回阶乘结果的位数
void factorial(int* fact, int digit, int num);
int find_pos(int* fact, int digit);
void process_carry(int* fact, int pos);
void output(int* fact, int digit, int num);

int main(void)
{
	int num, digit;
	int* fact = NULL;

	scanf("%d", &num);//输入求阶乘的数:num!
	digit = find_digit(num);
	if (!(fact = (int*)calloc(digit , sizeof(int))))//动态分配并初始化为0
	{
		printf("分配数组空间失败!
");
		return -1;
	}
	factorial(fact, digit,num);
	output(fact, digit, num);

	free(fact); fact = NULL;
	return 0;
}
int find_digit(int num)
{
	double digit_f = 0;
	for (int i = 1; i <= num; i++)
	{
		digit_f += log10(i);
	}
	return (int)digit_f + 1;
}
void factorial(int* fact, int digit, int num)
{
	int pos;//最高位的位数
	fact[0] = 1;//设置第一位为1:0! = 1! = 1
	for (int i = 2; i <= num; i++)
	{
		pos = find_pos(fact, digit);
		for (int j = 0; j <= pos; j++)
		{
			fact[j] *= i;
		}
		process_carry(fact, pos);
	}

}
int find_pos(int* fact, int digit)
{
	for (int i = digit - 1; i >= 0; i--)//找到最高位
	{
		if (fact[i] != 0)
		{
			return i;
		}
	}
}
void process_carry(int* fact, int pos)
{
	int carry = 0;//进位
	for (int i = 0; i <= pos; i++)
	{
		fact[i] += carry;
		if (fact[i] <= 9)
		{
			carry = 0;
		}
		if (fact[i] > 9 && i < pos)// 此时不是最高位
		{
			carry = fact[i] / 10;
			fact[i] %= 10;
		}
		if (fact[i] > 9 && i == pos)// 此时为最高位
		{
			while (fact[i] > 9)
			{
				carry = fact[i] / 10;
				fact[i] %= 10;
				fact[++i] = carry;
			}
		}
	}
}
void output(int* fact, int digit, int num)
{
	int n = 0;
	int m = 0;
	int pos = find_pos(fact, digit);//最高位的索引
	printf("
输出%d的阶乘结果: 
", num);
	for (int i = pos; i >= 0; i--)
	{
		printf("%d", fact[i]);
		if (++m % 3 == 0)//每三个数字凑一组
		{
			printf(" ");
		}
		if (m == 3 * 13)//每一行输出13组
		{
			printf("
");
			m = 0;
		}
	}
	printf("

%d!共有%d位。
", num, pos + 1);
}

输出结果:

在这里插入图片描述

在这里插入图片描述

原文地址:https://www.cnblogs.com/ziyang1060/p/13109900.html