C语言 数的阶乘、高次幂、大数加法及大数乘法

本文所有代码只适用于非负数,负数思路与整数相同,仅需处理符号,不再赘述。

大数加法

基本思路:将数字倒序放入数组中处理,这样从头到尾符合计算顺序,进位方便,并且不用考虑对齐。其余同普通加法过程。输出时倒序输出。
代码如下:

#include<stdio.h>
#include <string.h>
int main() {
	char num1[10000];
	char num2[10000];
	char c;
	int t,tem,i,len1=0,len2=0;//t 进位
	while(scanf("%c",&c)&&c!='\n') {
		num1[len1++]=c;
	}
	while(scanf("%c",&c)&&c!='\n') {
		num2[len2++]=c;
	}//录入数据
	for(i=0; i<len1/2; i++) {
		c=num1[i];
		num1[i]=num1[len1-i-1];
		num1[len1-i-1]=c;
	}
	for(i=0; i<len2/2; i++) {
		c=num2[i];
		num2[i]=num2[len1-i-1];
		num2[len2-i-1]=c;
	}//翻转
	t=0;
	if(len1>len2) { //选择长位数保存结果
		for(i=0; i<len2; i++) {
			tem=num1[i]-'0'+num2[i]-'0'+t;
			t=tem/10;
			num1[i]=tem%10+'0';
		}
	} else {
		for(i=0; i<len1; i++) {
			tem=num2[i]-'0'+num2[i]-'0'+t;
			t=tem/10;
			num2[i]=tem%10+'0';
		}
	}
	if(t) { //处理进位
		if(len1>len2) { //选择长位数保存进位
			for(i; i<len1; i++) {
				tem=num1[i]-'0'+t;
				t=tem/10;
				num1[i]=tem%10+'0';
				if(t==0) {
					break;
				}
			}
		} else {
			for(i; i<len2; i++) {
				tem=num2[i]-'0'+t;
				t=tem/10;
				num2[i]=tem%10+'0';
				if(t==0) {
					break;
				}
			}
		}
	}
	if(t) { //位数溢出
		printf("%d",t);
	}
	if(len1>len2) {
		for(i=len1-1; i>=0; i--)
			printf("%c",num1[i]);
	} else {
		for(i=len2-1; i>=0; i--)
			printf("%c",num2[i]);
		}
	return 0;
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------

大数乘法

普通思路:模拟乘法过程,将位数较少的因子分解为一个一个的数与长位数的因子进行乘法,需要补零时补零,结果保存至中间变量,然后用中间变量与当前的结果进行加法(当前结果个位数初始化为0)。最后输出。仍旧采用倒序。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *multiply(int num, char *obj) {//单个数字进行大数计算,单次相乘不可超过int
	int i, tem, t = 0;
	char ttt[25];
	if (num == 0) {
		obj[0] = '\0';
		return obj;
	}
	if (num == 1) {
		return obj;
	}
	for (i = 0; i < strlen(obj); i++) {
		tem = (obj[i] - '0')*num + t;
		t = tem / 10;
		obj[i] = tem % 10 + '0';
	}
	if (t) {
		itoa(t, ttt, 10);
		for (i = 0; i < strlen(ttt) / 2; i++) {
			char c = ttt[i];
			ttt[i] = ttt[strlen(ttt) - i - 1];
			ttt[strlen(ttt) - i - 1] = c;
		}//翻转
		obj = strcat(obj,ttt);
	}
	return obj;
}
char *add(char *num1, char *num2) {//大数加法
	int tem, t, i, len1 = strlen(num1), len2 = strlen(num2);
	t = 0;
	if (len1 < len2)
		for (i = 0; i < len1; i++) {
			tem = num1[i] - '0' + num2[i] - '0' + t;
			t = tem / 10;
			num2[i] = tem % 10 + '0';
		}
	else {
		for (i = 0; i < len2; i++) {
			tem = num1[i] - '0' + num2[i] - '0' + t;
			t = tem / 10;
			num1[i] = tem % 10 + '0';
		}
	}
	if (t) { //处理进位
		if (len1>len2)//数组1 
			for (i = len2; i<len1; i++) {
				tem = t + num1[i] -'0';
				t = tem / 10;
				num1[i] = tem % 10 + '0';
				if (t == 0) {
					break;
				}
			}
		else {//数组2
			for (i = len1; i<len2; i++) {
				tem = t + num2[i] - '0';
				t = tem / 10;
				num2[i] = tem % 10 + '0';
				if (t == 0) {
					break;
				}
			}
		}
		if (t) {
			if (len1 > len2) {
				num1[len1 + 1] = '\0';
				num1[len1] = t + '0';
			}
			else {
				num2[len2 + 1] = '\0';
				num2[len2] = t + '0';
			}
		}
	}
	if (len1 > len2) {//判断该返回那个
		return num1;
	}
	else {
		return num2;
	}
}
char *addzero(char *num, int n) {//在字符串前加n个零
	int i;
	char tem[10008];
	for (i = 0; i < n; i++) {
		tem[i] = '0';
	}tem[i] = '\0';
	num = strcat(tem,num);
	return num;
}

int main() {
	char obj[10005], numtem[10005], num[105], number[105];
	int len = 0, len1 = 0, len2 = 0, i;
	char c;
	printf("请输入两个数字\n");
	rewind(stdin);
	while (scanf("%c", &c) && c != '\n'&&c != ' ') {
		num[len1++] = c ;
	}num[len1] = '\0';
	while (scanf("%c", &c) && c != '\n'&&c != ' ') {
		number[len2++] = c ;
	}number[len2] = '\0';
	if (strcmp(num, "0") == 0 || strcmp(number, "0") == 0) {
		printf("0");
	}//两因数中一个为0
	else {
		for (i = 0; i < len1 / 2; i++) {
			c = num[i];
			num[i] = num[len1 - i - 1];
			num[len1 - i - 1] = c;
		}
		for (i = 0; i < len2 / 2; i++) {
			c = number[i];
			number[i] = number[len2 - i - 1];
			number[len2 - i - 1] = c;
		}//翻转
		for (i = 0; i < 10005; i++) {
			obj[i] = '0';
		}obj[i - 1] = '\0';//初始化
		if (len1 < len2) {
			for (i = 0; i < len1; i++) {
				char ttt[105];
				strcpy(ttt, number);
				strcpy(numtem, multiply(num[i] - '0', ttt));
				strcpy(numtem, addzero(numtem, i));
				strcpy(obj, strcpy(numtem, add(obj, numtem)));
			}
		}
		else {
			for (i = 0; i < len2; i++) {
				char ttt[105];
				strcpy(ttt, num);
				strcpy(numtem, multiply(number[i] - '0', ttt));
				strcpy(numtem, addzero(numtem, i));
				strcpy(obj, strcpy(numtem, add(obj, numtem)));
			}
		}
		//判断输出位数
		//两数相乘	结果为两个因数位数和或者位数和减一
		if (obj[len1 + len2 - 1] >'0'&&obj[len1 + len2 - 1]<='9') {
			printf("%c", obj[len1 + len2 - 1]);
		}
		for (i = len1 + len2 - 2; i >= 0; i--) {
			printf("%c", obj[i]);
		}printf("\n");
		//puts(obj);
	}
	return 0;
}

这个方法容易想到,但是操作麻烦。效率也低。
我将结果通过判断保存在较长数组的做法也使得代码较为冗长

--------------------------------------------------------------------------------------------------------------------------------------------------------------

阶乘/高次幂

  • 阶乘
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char *multiply(int num, char *obj) {//单个数字进行大数计算
	int i, tem, t = 0;
	char ttt[25];
	if (num == 0) {
		obj[0] = '\0';
		return obj;
	}
	if (num == 1) {
		return obj;
	}
	for (i = 0; i < strlen(obj); i++) {
		tem = (obj[i] - '0')*num + t;
		t = tem / 10;
		obj[i] = tem % 10 + '0';
	}
	if (t) {
		itoa(t, ttt, 10);
		for (i = 0; i < strlen(ttt) / 2; i++) {
			char c = ttt[i];
			ttt[i] = ttt[strlen(ttt) - i - 1];
			ttt[strlen(ttt) - i - 1] = c;
		}//翻转
		obj = strcat(obj,ttt);
	}
	return obj;
}

int main() {
	printf("请输入数字:\n");
	int n,i,len;
	char num[10005];
	scanf("%s",num);
	n=atoi(num);
	len=strlen(num);
	for(i=0; i<len/2; i++) {
		char c=num[i];
		num[i]=num[len-i-1];
		num[len-i-1]=c;
	}//翻转
	if(n==0||n==1) {
		printf("1");
	} else if(n>0) {
		n--;//n已在数组中 
		while(multiply(n--,num)&&n>1);
		for(i=strlen(num)-1; i>=0; i--) {
			printf("%c",num[i]);
		}
	}
	return 0;
}

  • 阶乘(二)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(){
	int num,i,j,tem,t=0;//t  进位 
	scanf("%d",&num);
	int obj[20000]={1},len=1;//len 当前数的长度 
	for(i=1;i<=num;i++){ 
		t=0;
		for(j=0;j<len;j++){//遍历相乘当前数组 
			tem=obj[j]*i+t;
			t=tem/10;
			obj[j]=tem%10;
		}
		while(j==len&&t!=0){//仍有进位 
			obj[len++]=t%10;
			t/=10;
		}
	}
	for(i=len-1;i>=0;i--){
		printf("%d",obj[i]);
	}
	return 0; 
}
  • 高次幂
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char *multiply(int num, char *obj) {//单个数字进行大数计算
	int i, tem, t = 0;
	char ttt[25];
	if (num == 1) {
		return obj;
	}
	for (i = 0; i < strlen(obj); i++) {
		tem = (obj[i] - '0')*num + t;
		t = tem / 10;
		obj[i] = tem % 10 + '0';
	}
	if (t) {
		itoa(t, ttt, 10);
		for (i = 0; i < strlen(ttt) / 2; i++) {
			char c = ttt[i];
			ttt[i] = ttt[strlen(ttt) - i - 1];
			ttt[strlen(ttt) - i - 1] = c;
		}//翻转
		obj = strcat(obj,ttt);
	}
	return obj;
}
int main() {
	int n,i,num;
	char obj[10000];
	printf("请输入底数,指数:\n");
	scanf("%s%d",obj,&n);
	num=atoi(obj);
	if (n == 0) {
		obj[0] = '1';
		obj[1] = '\0';
	}
	if(n==0&&num==0) {
		printf("error");
	}
	int len=strlen(obj);
	for(i=0;i<len/2;i++){
		char c=obj[i];
		obj[i]=obj[len-i-1];
		obj[len-i-1]=c;
	}//翻转 
	for(i=1; i<n; i++) {//本身就是一次方 
		multiply(num,obj);
	}
		for(i=strlen(obj)-1; i>=0; i--) {
			printf("%c",obj[i]);
		}
	return 0;
}
  • 高次幂(二)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {
	int num,n,i,j;//num 底数   n  指数
	printf("请输入底数,指数:\n");
	char obj[20000]= {0},len,t,tem;
	scanf("%s%d",obj,&n);//len 当前数的长度
	len=strlen(obj);
	num=atoi(obj);
	if(n==0) {
		if(num==0) {
			printf("error");
		}else{
			printf("1");
		}
	} else {
		for(i=1; i<n; i++) {
			t=0;
			for(j=0; j<len; j++) {
				tem=(obj[j]-'0')*num+t;
				t=tem/10;
				obj[j]=tem%10+'0';
			}
			while(j==len&&t!=0) {
				obj[len++]=t%10+'0';
				t/=10;
			}
		}
		for(i=len-1; i>=0; i--) {
			printf("%c",obj[i]);
		}
	}
	return 0;
}
posted @ 2018-05-24 23:32  kafm  阅读(402)  评论(0编辑  收藏  举报