这是一道难度等级为4的题目

题目计算的部分很容易就实现了

阶乘还有2的i次方都用递归计算,很方便

只需要把i=0时候的这种特殊情况处理好就行

unsigned int factorial(int n){	//递归调用计算n的阶乘
	if(n>0)
		return n*factorial(n-1);
	else 
		return 1;
}

unsigned int two_power_i(int i){		//计算2^i
	if(i>0)
		return 2*two_power_i(i-1);	
	else ;
		return 1;
}

 

至于后半部分的出错处理方式,最大值MAXINT的问题我一开始理解的是

像Python或者是Excel函数那样,会有专门的处理错误的语句

Python中错误处理方式

但是百度了一圈之后,只找到了这个 C 错误处理 | 菜鸟联盟

跟我想的有点儿不太一样,看来C语言好像不支持这种操作

而且经过我的试验,通过对全局变量errno的观察,发现即使发生int类型发生溢出,errno的值不会发生改变,说明int数据溢出,并不算一种C收录进去的错误

用errno这个思路行不通

 

后来又想到,默认设置MAXINT为无符号32位int类型

计算出32位二进制的最大值 并初始化MAXINT为2^32-1,将计算得到的结果tmp(强制转化为64位)与MAXINT比较

如果tmp>MAXINT  那么按出错处理

 

尽管觉得这样不是很妥当,毕竟如果支持64位int型,为何不直接将数组扩大到64位的longlongint上去,而非要钳制在32位呢

 

写完了程序,感觉基本功能实现了

 

翻一下课后答案,里面提到,既然超出最大值,那么就不能用比大小的方式

而我恰恰是用的这个方式

改!

通过前面的试验发现,当发生溢出之后,虽然不会报错,但是很明显,原来一直递增的数组序列,会出现反而减小的情况

利用这个特点,只需要检测相邻两次的数组值,很容易就可以发现结果溢出的情况,进而检测出错误,程序对应给出相应的处理方式

在这里,计算结果是不断增大的,一旦溢出,则在计算下去没有意义,我选择结束计算

 

同时,利用这个方法,可以很容易的将原来32位的MAXINT  扩展为64位

下面附上完整的代码:

#include <stdio.h>
#include <errno.h>
#include <string.h>

#define arrsize 40		//定义数组大小20
//#define MAXINT  4294967295
 
//extern int errno ;		//引用全局变量

unsigned int factorial(int n){	//递归调用计算n的阶乘
	if(n>0)
		return n*factorial(n-1);
	else 
		return 1;
}

unsigned int two_power_i(int i){		//计算2^i
	if(i>0)
		return 2*two_power_i(i-1);	
	else ;
		return 1;
}

int main(){
	int n;
	unsigned long long tmp;
	unsigned long long  int a[arrsize]={};
	printf("a[arrsize]大小为%d Byte (%d bit)\n",sizeof(a[0]),sizeof(a[0])*8);
	printf("请输入n的值:");
	scanf("%d",&n);
	while(n>arrsize||n<0){
		printf("n的值不合法,0<=n<=%d请重新输入:",arrsize);
		scanf("%d",&n);
	}

	for(int i=0;i<n;i++){
		tmp=(unsigned long long int)factorial(i)*(unsigned long long int)two_power_i(i);
//		printf("%d!  = %u \n",i,factorial(i));
//		printf("2^%d = %u \n",i,two_power_i(i));
//		printf("sizeof(tmp)=%u\ttmp=%llu\n",sizeof(tmp),tmp);
//		if(tmp>MAXINT||tmp==0){

		a[i]=tmp;
		if(a[i]<a[i-1]&&i>0){
			printf("k!*2^k > MAXINT,将不再往后计算,程序结束!\n");
			printf("MAXINT为无符号 long long类型 最大为2^64-1\n");
//			printf("a[i-1]=%llu\n",a[i-1]);
			return -1;
		}
		printf("a[%d]\t=%llu \n",i,a[i]);
	}

}

运行结果:

尽管我n给到了40,但是实际在n=20的时候,结果就已经比64位二进制支持的最大结果还大,发生溢出,经过检验,结果正确,程序运行正常,对于不合理的n输入,也有相应的处理方法

 

 

 

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐