算法一:关于大数运算的阶乘 (基=10) c语言程序代码注释


大数运算也是刚刚接触 ,因此找了资料和代码熟悉下。从搜索情况来看,阶乘被人提及比较多。因此我也在搜到文章中 选了一个代码,进行了注释。

 

代码不难,是一位博主写的。但是代码没有注释,我为了方便以后自己观看 和 与大家交流 贴出来分享下 。可能有些地方不是很对,欢迎指正,杜绝恶意评价。

下期预告:十六进制转成十进制,特别之处在于可以输入任意长度的十六制,也属大数运算。

网上有类似的,但希望自己能有一个学习过程的记录。 希望自己能坚持更新下来。贵在坚持

 

 

#include "stdint.h"
#include "string.h"
#include "stdio.h"



//定义short int 为 s_int 16位 
#define 	s_int	short int
//定义最大的位数(指结果值) 
#define		MAXDIGIT		50000
//定义权 也就是基数为10   
#define 	RADIX			10 


//定义一个函数实现进位
//返回值为bool 表明正确与否
bool carry(s_int result[],int &dgts){
	int i;
	s_int carry_value = 0;
	
	//这里将上次计算得到的结果值(未进位) 并告知当前结果值占的位数 
	//比如上次 3! * 4后=24 但是是存储在result[0]中的 digits=0
	//当然下面的肯定不会执行(因为digits=0) 不要急  因为它的
	//下面一个就是处理他的问题 
	for(i=0;i<dgts;i++)
	{
		result[i] +=carry_value	;//从最低位开始计算  初始进位值为0
		//判断该位是否需要进位 然后计算进位值
		//比如12 那么进位为1(添加到result[1]上) 余数为2(存储在result[0]) 
		carry_value =(result[i]< RADIX)?0:(result[i]/RADIX); 
		result[i] -= carry_value * RADIX;	//进位后以后得到的该位置值 
	} 
	//处理最后一位 
	//若需要进位,则循环进位,直到需要进位为止
	//注意 这里i是+1后的 
	result[i] += carry_value; 
	while(result[i]>=RADIX && i<MAXDIGIT)
	{
 		 carry_value = result[i] / RADIX;
         result[i] -= carry_value * RADIX;
         result[++i] = carry_value;
         ++dgts;
	} 
	if(i >= MAXDIGIT)
		return false;
		
	return true;
} 
//定义一个阶乘函数 factorial 
//返回值是一个int类型 其实就是标志  出错就返回-1 
//传入n 即 你要求的那个数的阶乘n! result 指代结果值 
int factorial(int n ,s_int result[]) {
	int digits = 0;	//位数记录 初始设为0
	result[0] = 1 ; //结果初始为1
	
	//0!=1
	if(n==0) return 1;//返回1只是表明计算正确 结果值其实在上面的初始化result[0]=1 
	
	//开始计算n! 这里我们从2开始 是因为1没有必要 
	//比如求4! 那么就是1 * 2 * 3 *4 所以这里用n+1 
	for(int i=2;i<n+1;i++){
		//以下都是前一次result[] 乘以i值 
		for(int j=0;j<=digits;++j)
		{
			//关键一步  如果一个数用数组来存储 
			/*
				举例: 5! 
				先看4! 
				4! = 3!* 4 = 2! * 3 * 4 
				2! = 2*1 省略1 就是i从2开始 
				得到的结果值存在result[]数组中 result每一个元素都能存0-9的数
				比如3!= 6那么存到result[0]中 4!= 24 那么只存到result[0]就不够了
				因为result[0]只能存0-9 但是结果是24 所以我们要把多余的放到result[1]中
				相当于进位了2 result[0] 只剩下4了 而result[1]原来是0 现在+2
				result[1] = 2;
				ok 现在来看5! =4!* 5 =24 * 5  
				24 不能用整体来看 而是分别存储在result[1] reuslt[0]中 2   4 来看
				那么*5 是最低位开始乘 也就是 4*5  即下文result[0] * 5  然后是
				result[1]* 5  先不进位  只是存储在各自的result[i]位中
				注意: result[]要计算多少位  是根据digits 位数来进行的 比如一开始
				digits = 0 是因为结果值只占一位 存储在result[0] 后来4!=24 那么就要
				存储到result[1] 和result[0]  digits=1 
			*/ 
			result[j] *= i;	 
		} 
		//上面已经把 计算结果值 写入到各自的位中  下面要判断进位  也就是 每乘以一个数就要判断进位一次
		//比如 9!=8!*9 =7!*8*9=...=1!*2 *3*...*9  每次都是上一次结果 * 数n(从2,3,4,5...9为止) 
		if(!carry(result,digits))
			break; 
		
	} 

} 
//定义一个打印函数
void print(s_int result[],const int &digits){
	
	int i;
	if(digits <10)
	{
		for(int i = digits;i>=0;i--)
		{
			printf("%d",result[i]);
		}
	}else{
		printf("%d.",result[digits]);
		for(i=digits-1;i>0;i--)
		{
			printf("%d",result[i]);
		}
		printf("E %d",digits);
	}
} 

//主程序入口 
int main(void)
{
	s_int result[MAXDIGIT];	
	int n;
	int digits;
	
	//提示信息 
	printf("Please input the number that you want to calulate the n!\n");
	//用户输入n 求n!
	scanf("%d",&n);
	
	//判断n值 限制条件可以自己设定 
	if(n < 0) {
		printf("Error:A positive integer is needed!");
		return 0;
	} 
	
	//主要算法和函数   函数包括:计算n! 和 打印结果值 
	if((digits = factorial(n,result))== -1){
		printf("over flow");
		return 0;
	}else
	{
		print(result,digits);
		return 0;
	}
	
	
}

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值