大整数加减乘除

用指定位数的数组存储大整数,每一位对应一位,若大整数长度小于数组长度,索引已0开始的称高位,高位补零

即int a[10]存储数值为:123456

a[0]  a[1]  a[2]  a[3] a[4]  a[5]  a[6]  a[7]  a[8] a[9] 

 0       0      0      0     1      2     3       4      5      6

简写:00000123456

这里的分析和实现为10进制当然可以类比为16进制,8进制,2进制

#1 大整数加法

分析:对位相加,若结果大于0,将结果-10,高位增1

实现如下:

/**
 * a,b为大整数的两个加数,c存储大整数加后结果,len为数组长度(即大整数最多位数)
 */
void bignum_add(int a[],int b[],int c[],int len){
	for(int i = 0; i <len; i++) c[i] = 0;
	for(int i = len-1; i >= 0; i--){
		c[i] += a[i]+b[i];
		if( c[i] >= 10){
			c[i]-=10;
			c[i-1] +=1;
		}
	}
}

#2 大整数减法

分析:对位相减后,若结果小于0,高位借一,将结果+10

实现:

void big_subtract(int a[],int b[],int len){
	int j;
	for(j = 0; j < len; j++) if(a[j] != 0) break;
	for(int i = len-1; i >= j; i--){
		a[i] = a[i]-b[i];
		if( a[i] < 0){
			a[i-1]-=1;
			a[i]+=10;
		}
	}
}

#3 大整数乘法

分析:

实现如下:

void bignum_multply(int a[],int b[],int c[],int len){
	for(int z = 0; z < len; z++) c[z] = 0;
	int i,j,k;
	for(i = 0; i <len; i++) if(a[i] != 0) break; //i++得到的高位所有0的个数 len-i即a的位数
	for(j = 0; j <len; j++) if(b[j] != 0) break; //同上 len-j即b的位数
	int x = 0;
	int y = 0;
	for(int m = len-1; m >= i; m--,x++){
		y = 0;
		for(int n = len-1; n >= j; n--,y++){
			c[len-1-(x+y)] += a[m]*b[n];
		}
	}
	for(k = 0; k <len; k++) if(c[k] != 0) break;
	for(; k < len; k++){
		//printf("%d ",c[k]);
		int time = 0;
		while(c[k]>=10) {
			c[k] -= 10;
			time++;
		}
		c[k-1] += time;
	}
	//printf(" \n i=%d j=%d x=%d y=%d \n",i,j,x,y);
}

#4 大整数除法

分析:

例:1000 / 23 

1‘ 我们要思考一个数是不是可以被一个数除

   所以,判断除数是否小于被除数,若小于则不能被除

2’ 4000/23 = 173.91,可以表示为195,R=21

    4000 - 2300*1 = 1700,

    1700 -  230*7 = 90,

    90  -  23*3 = 21 = R

   根据如上步骤我们可以得出规律

 1‘  除数左移n位低位补0 ,最多移位为被除数位数-除数位数(被除数为n位,除数为m位,则商最多整数位为n-m位)

  2’ 将除数左移位数 至 被除数长度时,若能减多少个数,个数对应商整数位,n=1,为个位,n=2为十位,n=3为百位......

  3‘ 直至不能被减得到余数R

实现如下:

// 判断是否可除,即可减
int a_bigger_b(int a[],int b[],int len){
	int i,j; //去除高位所有0后i,j为大数开始下标
	for(i = 0; i < len; i++) if(a[i] != 0) break;
	for(j = 0; j < len; j++) if(b[j] != 0) break;
	// 被除数和除数位数不一样
	if((len-i) != (len-j)) return (len-i) > (len-j);
	for(; i < len; i++){
		if(a[i] < b[i]) return 0;
		else if(a[i] == b[j]) continue;
		else return 1; //最高位大于则可以做减法
	}
	return 1;
}
//低位补领零或加零
//	sub_or_add_zero(1,num1, num_maxlen,4);左移4位,地位补0
//	sub_or_add_zero(0,num1, num_maxlen,3);右移三位,高位补0
void sub_or_add_zero(int flag,int b[],int len,int num){
	int i; //去除高位所有0后i,j为大数开始下标
	for(i = 0; i < len; i++) if(b[i] != 0) break;
	if(flag==1){
		//移位
		for(; i < len; i++){
			b[i-num] = b[i];
		}
		//移位后附0
		for(int j = len -1; j >= (len-num);j--){
			b[j]=0;
		}
	}
	else if(flag==0){
		//移位除零
		for(int j = len - 1; j >= i; j--){
			b[j] = b[j-num];
		}
		while(num){
			b[i+num-1] = 0;
			num--;
		}
	}
}

int bignum_divide(int a[],int b[],int len){
	int i,j; //去除高位所有0后i,j为大数开始下标
	for(i = 0; i < len; i++) if(a[i] != 0) break;
	for(j = 0; j < len; j++) if(b[j] != 0) break;
	int ans = 0;
	sub_or_add_zero(1,b,len,j-i);
	for(int k = 0; k <= (j-i); k++){ //长度相等循环一次
		int time = 0;
		while(a_bigger_b(a, b, len)==1){
			big_subtract(a, b, len);
			time++;
		}
		if(a_bigger_b(a, b, len) == a_bigger_b(b, a, len)) time = 1;
		ans = ans*10 +time;
		sub_or_add_zero(0,b,len,1);
	}
	return ans;
}

测试结果:

int main(void){
	int num_maxlen = 100;
	int num1[num_maxlen];
	printf("-------pow(x,n) x^n--------\n");
	int x = 2;
	int n = 100;
	bignum_pow(x,n,num1,num_maxlen);
	printf("%d^%d result :",x,n);print_bignum(num1, num_maxlen);
	printf("\n---------------\n");
	int num2[num_maxlen];
	bignum_pow(3,1,num2,num_maxlen);
	printf("-------bitnum to add--------\n");
	int num3[num_maxlen];
	printf("the bignums are :[");print_bignum(num1, num_maxlen);printf("] , [");print_bignum(num2, num_maxlen);printf("]");
	bignum_add(num1,num2,num3,num_maxlen);
	//big_subtract(num1,num2,num3,num_maxlen);
	printf("\nresult :");print_bignum(num3, num_maxlen);
	printf("\n---------------\n");
	printf("-------bitnum to multply--------\n");
	int num4[num_maxlen];
	printf("the bignums are :[");print_bignum(num1, num_maxlen);printf("] , [");print_bignum(num2, num_maxlen);printf("]");
	bignum_multply(num1,num2,num4,num_maxlen);
	printf("\nresult :");print_bignum(num4, num_maxlen);
	printf("\n---------------");
	printf("-------biStnum to divide--------\n");
	printf("the bignums are :[");print_bignum(num1, num_maxlen);printf("] , [");print_bignum(num2, num_maxlen);printf("]");
	printf("\nresult : ans = %d R=",bignum_divide(num1, num2, num_maxlen));print_bignum(num1, num_maxlen);
	printf("\n---------------");
	return 0;
}

result:

-------pow(x,n) x^n-------------------------
2^100 result :1267650600228229401496703205376
---------------------------------------------------
-------bitnum to add-------------------------
the bignums are :[1267650600228229401496703205376] , [3]
result :1267650600228229401496703205379
---------------------------------------------------
-------bitnum to multply---------------------
the bignums are :[1267650600228229401496703205376] , [3]
result :3710295180068468820448101096151128
----------------------biStnum to divide--------
the bignums are :[1267650600228229401496703205376] , [3]
result : ans = 1431655765 R=1
-----------------------------------------------------

在C语言中,由于其标准数据类型有大小限制,直接进行大整数加减乘除运算可能会超出范围。为了处理大整数运算,我们通常需要采用字符串或数组的方式存储大整数,并实现大数运算的函数。以下是一个简化的大整数加法的示例实现: 1. 首先定义大整数存储结构,可以使用字符数组或字符串来表示一个大整数。 2. 然后编写大数加法的函数,通常需要逆序处理字符串中的每一位数字,模拟手算的过程。 下面是一个简化版的C语言大整数加法函数的示例: ```c #include <stdio.h> #include <string.h> #include <stdlib.h> // 反转字符串函数 void reverse(char* str) { int length = strlen(str); for (int i = 0; i < length / 2; i++) { char temp = str[i]; str[i] = str[length - i - 1]; str[length - i - 1] = temp; } } // 大整数加法函数 void bigIntAdd(char* num1, char* num2, char* result) { int len1 = strlen(num1); int len2 = strlen(num2); int maxLen = len1 > len2 ? len1 : len2; int carry = 0; // 进位 reverse(num1); // 翻转字符串以便从最低位开始相加 reverse(num2); reverse(result); // 结果也需要翻转,最后翻回去 for (int i = 0; i < maxLen; i++) { int digit1 = i < len1 ? num1[i] - '0' : 0; int digit2 = i < len2 ? num2[i] - '0' : 0; int sum = digit1 + digit2 + carry; result[i] = (sum % 10) + '0'; // 计算和,加上进位,并转换为字符 carry = sum / 10; // 计算新的进位 } if (carry > 0) { result[maxLen] = carry + '0'; // 如果最后还有进位,直接加到结果的最后 result[maxLen + 1] = '\0'; // 字符串结束符 } else { result[maxLen] = '\0'; // 结束符 } reverse(result); // 最后翻转回正常的顺序 } int main() { char num1[100], num2[100], result[102]; // 假设大整数不会超过100位 printf("请输入第一个大整数:"); scanf("%s", num1); printf("请输入第二个大整数:"); scanf("%s", num2); bigIntAdd(num1, num2, result); printf("结果是:%s\n", result); return 0; } ``` 这段代码仅实现了大整数加法运算。如果需要实现减法、乘法和除法,需要编写额外的函数来处理这些运算。大整数减法需要处理借位的情况,乘法需要实现大整数逐位相乘并加到结果的相应位置,并处理进位,除法则更为复杂,需要实现长除法或通过循环减去除数的方法来得到商和余数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值