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


    大家好,我是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);
    }
    

    输出结果:

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    经典数字信号处理图书的个人评述
    信号与系统
    FFT结果的物理意义
    如何选导师,如何做好研究生,如何做好同行评审
    Google学术指数2015版
    2015影响因子Excel版
    VHDL MOD和REM(转)
    面向对象的三大特征
    【数据结构与算法】内部排序之一:插入排序和希尔排序的N中实现(不断优化,附完整源码)
    JAVA字符串String、StringBuffer、StringBuilder、基本数据类型包装
  • 原文地址:https://www.cnblogs.com/ziyang1060/p/13109900.html
Copyright © 2020-2023  润新知