zoukankan      html  css  js  c++  java
  • 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!='
    ') {
    		num1[len1++]=c;
    	}
    	while(scanf("%c",&c)&&c!='
    ') {
    		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] = '';
    		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] = '';
    				num1[len1] = t + '0';
    			}
    			else {
    				num2[len2 + 1] = '';
    				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] = '';
    	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("请输入两个数字
    ");
    	rewind(stdin);
    	while (scanf("%c", &c) && c != '
    '&&c != ' ') {
    		num[len1++] = c ;
    	}num[len1] = '';
    	while (scanf("%c", &c) && c != '
    '&&c != ' ') {
    		number[len2++] = c ;
    	}number[len2] = '';
    	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] = '';//初始化
    		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("
    ");
    		//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] = '';
    		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("请输入数字:
    ");
    	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("请输入底数,指数:
    ");
    	scanf("%s%d",obj,&n);
    	num=atoi(obj);
    	if (n == 0) {
    		obj[0] = '1';
    		obj[1] = '';
    	}
    	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("请输入底数,指数:
    ");
    	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;
    }
    
  • 相关阅读:
    poj3905 2sat!
    poj3648,2-sat求解
    poj2723 2sat判断解+二分
    hdu3622 2-sat问题,二分+判断有无解即可。
    poj2767,单向连通图判定,缩点+重新建图+新图DFS
    poj2186 求有向图G中所有点都能到达的点的数量
    poj2553 有向图缩点,强连通分量。
    poj 1236+hdu2767 有向图 缩点+看度数(tarjan)
    poj3694+hdu2460 求桥+缩点+LCA/tarjan
    dfs + 最小公倍数 Codeforces Round #383 (Div. 2)
  • 原文地址:https://www.cnblogs.com/kafm/p/12721866.html
Copyright © 2011-2022 走看看