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;
}