大数加法&大数减法 C语言实现

一、题目描述

 

二、输入样例

1 1

三、输出样例

2

四、思路

是道oj上的作业题

太复杂了

做完加法还有一大半过不了

才发现还有负数的情况

因为整型变量局限的问题

所以肯定是用字符串的方式输入

我的分法一共是三种(但最后还是做了四种)

        1.正数 正数(最原始版本)

        2.负数 负数(去掉负号做加法)

        3.一正 一负

1.正数+正数

输入字符串str1

输入字符串str2

计算字符串长度str1_len=strlen(str1)

计算字符串长度str2_len=strlen(str2)

算出数字更大的一个声明为len_max

倒序输出str1 将其每个字符元素变为整型 存入整型数组a中

倒序输出str2 将其每个字符元素变为整型 存入整型数组b中

定义一个整型数组c作为结果

定义一个k 作为进位(记得先初始化为0)

将(a[i]+b[i]+k)%10 作为结果放进c[i]中

将(a[i]+b[i]+k)/ 10 作为k进入下一步计算中

最后 如果 k>1的话 就先输出k

注意:

1、要先把a和b全部初始化为0,不然可能会有个比较短的数组的位置上没有数字,相加的时        候可能就会出问题 

2、还有就是 其实我一开始没有倒序去存入数组

     这样就会有溢出的时候没有办法解决的问题出现

     例如 90 + 80 = 170

 3、在字符串转换为整型数组的时候

       i  从 str1_len-1 到 0( i 代指的是字符串下标)

      例如长度为5

      数到 str1 [4] 就够了

 代码实现

if(str1[0]!='-'&&str2[0]!='-'){
		str1_len=strlen(str1);
		str2_len=strlen(str2);
		for(i = 0, j = str1_len - 1; j >= 0; i++, j--)     /*将字符数组逆序转换为整形数组*/
	    {
	        a[i] = str1[j] -'0';
	    } 
	    for(i = 0, j = str2_len - 1; j >= 0; i++, j--)
	    {
	        b[i] = str2[j] -'0';
	    } 
	    len_max=str1_len>str2_len?str1_len:str2_len;
		for(i=0;i<len_max;i++){ 
			c[i]=(a[i]+b[i]+k)%10;
			k=(a[i]+b[i]+k)/10;
		} 
		if(k!=0){
			printf("%d",k);
		}
		for(i=len_max-1;i>=0;i--){
			printf("%d",c[i]);
		}
	} 

2.负数 + 负数

和1其实没啥差 就是把在做转换为整型数组的时候把str1[0] str2[0]去掉

else if(str1[0]=='-'&&str2[0]=='-'){
		str1_len=strlen(str1);
		str2_len=strlen(str2);
		for(i = 0, j = str1_len - 1; j > 0; i++, j--)     /*将字符数组逆序转换为整形数组*/
	    {
	        a[i] = str1[j] -'0';
	    } 
	    for(i = 0, j = str2_len - 1; j > 0; i++, j--)     /*去掉j=0*/
	    {
	        b[i] = str2[j] -'0';
	    } 
	    len_max=str1_len>str2_len?str1_len:str2_len;
		for(i=0;i<len_max-1;i++){                         /*做加法时去掉一位*/
			c[i]=(a[i]+b[i]+k)%10;
			k=(a[i]+b[i]+k)/10;
		} 
		printf("-");                                      /*先输出-*/
		if(k!=0){
			printf("%d",k);
		}
		for(i=len_max-2;i>=0;i--){
			printf("%d",c[i]);
		}
	} 

 3. 一正 + 一负(大数减法)

两个数分成 被减数减数

这里默认为str1为正 str2为负

前面的步骤都是一样的

不过 减数长度会减一(把减号去掉)

先判断这两个一不一样

如果完全相同就直接输出0

否则则判断两个数的模哪一个更大

        引入n

        当长度不同时 长度长的字符串对应的数字一定更大 

        如果str1长    n>0

        如果str2长    n<0

        长度相同时  引入库函数strcmp(不过需要注意要把减数去掉负号再放进来)

如果n>0 就|str1|-|str2|

如果n<0 就|str2|-|str1| 最后输出前加个符号

减法运算

        当n>0时

        当a[i]-b[i]>0时

        c[i]=a[i]-b[i]

        当a[i]-b[i]<0时

        c[i]=a[i]+10-b[i]

        a[i+1] - -

还有需要注意的点是

例如 1800 - 1788 = 12

c = 0021

要把头的0消除掉

代码实现

	else if(str2[0]=='-'){
		str1_len = strlen(str1);
		str2_len = strlen(str2)-1;
		for(i = 0, j = 1  ; j <= str2_len; i++, j++)
	    {
	        str2[i] = str2[j];
	    } 
		len_max=str1_len>str2_len?str1_len:str2_len;
		if(str1_len>str2_len)
			n = 1;
		else if(str1_len==str2_len)
			n = strcmp(str1,str2);
		else 
			n = -1;

		for(i = 0, j = str1_len - 1; j >= 0; i++, j--)     /*将字符数组逆序转换为整形数组*/
	    {
	        a[i] = str1[j] -'0';

	    }
	
	    for(i = 0, j = str2_len -1; j >= 0; i++, j--)
	    {
	        b[i] = str2[j] -'0';
	    } 

		if(str1_len==str2_len){
			for(i=0;i<str1_len;i++){
				if(a[i]==b[i]){
					flag=0;
				}
				else{
					flag=1;
					break;
				}
			}
		}
		if(flag==0){
			printf("%d",0);
		}else{
		
		for(i=0; i<len_max; i++)
		{
			if(n>=0)
			{
				if(a[i]-b[i] >= 0)
					c[i] = a[i] - b[i];
				else 
				{
					c[i] = a[i] + 10 - b[i];
					a[i+1]--;
				}
			}
			else 
			{
				if(b[i]-a[i] >= 0)
					c[i] = b[i] - a[i];
				else
				{
					c[i] = b[i] + 10 - a[i];
					b[i+1]--;

				}
			}
		}
		if(n<0)
			printf("-");
		for(i=len_max-1;i>=0;i--){
			if(c[i]==0){
				cnt++;
				}
			else
				break;
			}
		for(i=len_max-1-cnt;i>=0;i--){
			printf("%d",c[i]);
		}
		}
	}

 五、代码实现

#include<stdio.h>
#include<string.h>
	char str1[100];
	char str2[100];
	int a[100];
	int b[100];
	int c[100];

int main()
{
	
	int i,j,k=0,str1_len,str2_len,len_max,cnt=0,n,flag=1;
	for(i=0;i<100;i++){               /*将整型数组a全部赋值为0*/
		a[i]=0;
	}
	for(i=0;i<100;i++){               /*将整型数组b全部赋值为0*/
		b[i]=0;
	}
	scanf("%s %s",&str1,&str2);
	if(str1[0]!='-'&&str2[0]!='-'){
		str1_len=strlen(str1);
		str2_len=strlen(str2);
		for(i = 0, j = str1_len - 1; j >= 0; i++, j--)     /*将字符数组逆序转换为整形数组*/
	    {
	        a[i] = str1[j] -'0';
	    } 
	    for(i = 0, j = str2_len - 1; j >= 0; i++, j--)
	    {
	        b[i] = str2[j] -'0';
	    } 
	    len_max=str1_len>str2_len?str1_len:str2_len;
		for(i=0;i<len_max;i++){ 
			c[i]=(a[i]+b[i]+k)%10;
			k=(a[i]+b[i]+k)/10;
		} 
		if(k!=0){
			printf("%d",k);
		}
		for(i=len_max-1;i>=0;i--){
			printf("%d",c[i]);
		}
	} 
	else if(str1[0]=='-'&&str2[0]=='-'){
		str1_len=strlen(str1);
		str2_len=strlen(str2);
		for(i = 0, j = str1_len - 1; j > 0; i++, j--)     /*将字符数组逆序转换为整形数组*/
	    {
	        a[i] = str1[j] -'0';
	    } 
	    for(i = 0, j = str2_len - 1; j > 0; i++, j--)
	    {
	        b[i] = str2[j] -'0';
	    } 
	    len_max=str1_len>str2_len?str1_len:str2_len;
		for(i=0;i<len_max-1;i++){ 
			c[i]=(a[i]+b[i]+k)%10;
			k=(a[i]+b[i]+k)/10;
		} 
		printf("-");
		if(k!=0){
			printf("%d",k);
		}
		for(i=len_max-2;i>=0;i--){
			printf("%d",c[i]);
		}
	} 
	else if(str2[0]=='-'){
		str1_len = strlen(str1);
		str2_len = strlen(str2)-1;
		for(i = 0, j = 1  ; j <= str2_len; i++, j++)
	    {
	        str2[i] = str2[j];
	    } 
		len_max=str1_len>str2_len?str1_len:str2_len;
		if(str1_len>str2_len)
			n = 1;
		else if(str1_len==str2_len)
			n = strcmp(str1,str2);
		else 
			n = -1;
		for(i = 0, j = str1_len - 1; j >= 0; i++, j--)     /*将字符数组逆序转换为整形数组*/
	    {
	        a[i] = str1[j] -'0';
	    }
	    for(i = 0, j = str2_len -1; j >= 0; i++, j--)
	    {
	        b[i] = str2[j] -'0';
	    } 
		if(str1_len==str2_len){
			for(i=0;i<str1_len;i++){
				if(a[i]==b[i]){
					flag=0;
				}
				else{
					flag=1;
					break;
				}
			}
		}
		if(flag==0){
			printf("%d",0);
		}else{
		
		for(i=0; i<len_max; i++)
		{
			if(n>=0)
			{
				if(a[i]-b[i] >= 0)
					c[i] = a[i] - b[i];
				else 
				{
					c[i] = a[i] + 10 - b[i];
					a[i+1]--;
				}
			}
			else 
			{
				if(b[i]-a[i] >= 0)
					c[i] = b[i] - a[i];
				else
				{
					c[i] = b[i] + 10 - a[i];
					b[i+1]--;
				}
			}
		}
		if(n<0)
			printf("-");
		for(i=len_max-1;i>=0;i--){
			if(c[i]==0){
				cnt++;
				}
			else
				break;
			}
		for(i=len_max-1-cnt;i>=0;i--){
			printf("%d",c[i]);
		}
		}
	}
	else {
		str1_len = strlen(str1)-1;
		str2_len = strlen(str2);
		len_max=str1_len>str2_len?str1_len:str2_len;
		for(i = 0, j = 1  ; j <= str1_len; i++, j++)
	    {
	        str1[i] = str1[j];
	    } 
		if(str2_len>str1_len)
			n = 1;
		else if(str2_len==str1_len)
			n = strcmp(str2,str1);
		else 
			n = -1;
		for(i = 0, j = str2_len -1; j >= 0; i++, j--)     /*将字符数组逆序转换为整形数组*/
	    {
	        a[i] = str2[j] -'0';
	    }
	    for(i = 0, j = str1_len -1; j >= 0; i++, j--)
	    {
	        b[i] = str1[j] -'0';
	    } 
		//printf("\n");
		if(str1_len==str2_len){
			for(i=0;i<str1_len;i++){
				if(a[i]==b[i]){
					flag=0;
				}
				else{
					flag=1;
					break;
				}
			}
		}
		if(flag==0){
			printf("%d",0);
		}else{
		for(i=0; i<len_max; i++)
		{
			if(n>=0)
			{
				if(a[i]-b[i] >= 0)
					c[i] = a[i] - b[i];
				else 
				{
					c[i] = a[i] + 10 - b[i];
					a[i+1]--;
				}
			}
			else 
			{
				if(b[i]-a[i] >= 0)
					c[i] = b[i] - a[i];
				else
				{
					c[i] = b[i] + 10 - a[i];
					b[i+1]--;
				}
			}
		}
		if(n<0)
			printf("-");
		for(i=len_max-1;i>=0;i--){
			if(c[i]==0){
				cnt++;
				}
			else
				break;
			}
		for(i=len_max-1-cnt;i>=0;i--){
			printf("%d",c[i]);
		}
	}
    } 
	return 0;
}

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是有符号大数的加减链表实现的 C 语言代码: ```c #include <stdio.h> #include <stdlib.h> /* 定义链表节点 */ typedef struct ListNode { int val; struct ListNode* next; } ListNode; /* 反转链表 */ ListNode* reverseList(ListNode* head) { ListNode* prev = NULL; ListNode* curr = head; while (curr) { ListNode* next = curr->next; curr->next = prev; prev = curr; curr = next; } return prev; } /* 删除链表头部的 0 */ ListNode* trimZero(ListNode* head) { while (head && head->val == 0) { ListNode* tmp = head; head = head->next; free(tmp); } return head; } /* 创建链表节点 */ ListNode* createNode(int val) { ListNode* node = (ListNode*)malloc(sizeof(ListNode)); node->val = val; node->next = NULL; return node; } /* 将数组转换为链表 */ ListNode* arrayToList(int* arr, int len) { ListNode* dummy = createNode(-1); ListNode* tail = dummy; for (int i = 0; i < len; i++) { ListNode* node = createNode(arr[i]); tail->next = node; tail = node; } return dummy->next; } /* 将链表转换为数组,并返回数组长度 */ int* listToArray(ListNode* head, int* len) { ListNode* curr = head; int count = 0; while (curr) { count++; curr = curr->next; } int* arr = (int*)malloc(sizeof(int) * count); curr = head; for (int i = 0; i < count; i++) { arr[i] = curr ? curr->val : 0; curr = curr ? curr->next : NULL; } *len = count; return arr; } /* 对链表进行加法运算 */ ListNode* add(ListNode* l1, ListNode* l2) { ListNode* dummy = createNode(-1); ListNode* tail = dummy; int carry = 0; while (l1 || l2) { int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + carry; carry = sum / 10; ListNode* node = createNode(sum % 10); tail->next = node; tail = node; l1 = l1 ? l1->next : NULL; l2 = l2 ? l2->next : NULL; } if (carry) { ListNode* node = createNode(carry); tail->next = node; tail = node; } return dummy->next; } /* 对链表进行减法运算 */ ListNode* subtract(ListNode* l1, ListNode* l2) { ListNode* dummy = createNode(-1); ListNode* tail = dummy; int borrow = 0; while (l1 || l2) { int diff = (l1 ? l1->val : 0) - (l2 ? l2->val : 0) - borrow; if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } ListNode* node = createNode(diff); tail->next = node; tail = node; l1 = l1 ? l1->next : NULL; l2 = l2 ? l2->next : NULL; } return dummy->next; } /* 对有符号大数进行加法运算 */ ListNode* addBigNumber(ListNode* l1, ListNode* l2) { // 处理符号位 int sign1 = l1->val < 0 ? -1 : 1; int sign2 = l2->val < 0 ? -1 : 1; if (sign1 * sign2 == 1) { // 同号相加 l1->val = abs(l1->val); l2->val = abs(l2->val); ListNode* result = add(l1, l2); result = trimZero(result); if (result == NULL) { result = createNode(0); } result->val *= sign1; return result; } else { // 异号相减 l1->val = abs(l1->val); l2->val = abs(l2->val); ListNode* result = NULL; if (sign1 == -1) { // l1 < 0, l2 > 0 result = subtract(l2, l1); } else { // l1 > 0, l2 < 0 result = subtract(l1, l2); } result = trimZero(result); if (result == NULL) { result = createNode(0); } result->val *= sign1; return result; } } /* 主函数 */ int main() { int a[] = {1, 2, 3, 4, -5, 6, 7, 8, 9}; int b[] = {9, 8, 7, -6, 5, 4, 3, 2, 1, 0}; int len1 = sizeof(a) / sizeof(int); int len2 = sizeof(b) / sizeof(int); ListNode* l1 = arrayToList(a, len1); ListNode* l2 = arrayToList(b, len2); ListNode* result = addBigNumber(l1, l2); int len = 0; int* arr = listToArray(result, &len); printf("Result: "); for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n"); free(arr); return 0; } ``` 该代码实现了对有符号大数进行加减法运算的功能。其中,每一个链表节点表示一个数字(可能为正数或负数),符号位存储在链表头节点中。函数 `add` 和 `subtract` 分别实现了链表的加法减法运算,函数 `addBigNumber` 判断两个数字的符号后,调用 `add` 或 `subtract` 进行相应的运算。最后,我们将结果从链表转换为数组并输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值