四则运算之加减法

问题描述

      计算机所能完成的一个基本功能就是完成数据的计算,譬如加法、减法等等。但是在任何一种计算机上,计算中能够使用的数字都是有一定范围的,超过了范围,就没法得到精确的结果。

      你现在接受了一个任务,要编写一个高精度计算器的核心部分。所谓高精度计算器,就是可以计算很大很大的数据的计算器。而你所需要编写的程序,就是真正完成高精度加法和高精度减法运算的两个函数,因为程序其它的部分已经由别人编写好了。

函数的输入、输出接口也已经定义完成,譬如 plus() 函数,它有三个参数 a、b 和 c,都是 char * 类型。a 和 b 分别是参加运算的两个整数,而 c 用来存放运算的结果。所有的数字都是以字符串的形式保存的。

注意,只需提交你自己编写的两个函数。

输入

输入的每一行是两个十进制的正整数和一个运算符,每个整数可以由最多 500 个数字组成。运算符可以是加号或者减号。

输出

对应着输入的每一行数据,输出计算的结果,每个结果占一行。

预设代码

前置代码
  1. /* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */  
  2.  
  3. #include <stdio.h>  
  4. #include <string.h>  
  5.   
  6. void plus(char *a, char *b, char *c);  
  7. void minus(char *a, char *b, char *c);  
  8.   
  9. int main()  
  10. {         
  11.     char a[1000];  
  12.     char b[1000];  
  13.     char c[1000];  
  14.     char s[2];  
  15.   
  16.     while (scanf("%s %s %s\n", a, s, b) == 3) {  
  17.         if (s[0] == '+') {  
  18.             plus(a, b, c);  
  19.         } else if (s[0] == '-') {  
  20.             minus(a, b, c);  
  21.         }  
  22.         printf("%s\n", c);  
  23.     }  
  24.   
  25.     return 0;  
  26. }  
  27.   
  28. /* PRESET CODE END - NEVER TOUCH CODE ABOVE */  

测试输入关于“测试输入”的帮助 期待的输出关于“期待的输出”的帮助 时间限制关于“时间限制”的帮助 内存限制关于“内存限制”的帮助 额外进程关于“{$a} 个额外进程”的帮助
测试用例 1 以文本方式显示
  1. 1 + 2↵
  2. 3 - 2↵
以文本方式显示
  1. 3↵
  2. 1↵
1秒 64M 0
题解思路

大致思路:

我用的思路是,先将a,b两个字符串倒序转化为整形数组,然后模拟加减法的竖式计算通过数组之间的“进位”来将最后的结果存入一个整形数组里面,最后再把这个整形数组转化为字符型的数组。

具体实现方式以及需要注意的事项:

首先预制的函数里面在输入中多了“/n”,这个我们在自己编写的时候可以先将其去掉,要不然读入的时候会有问题。

然后就是进行字符串的转化,需要注意的是需要先把字符串前面的前导0去掉,借用大神的方法while(a[0]=='0')a++;while(b[0]=='0')b++;这样就可以吧字符串前面的前导0去掉。但是应该注意字符串a=“0000”或b=“00000”的这种情况,这种情况下会导致,把字符串清空,这里需要判断一下,如果经过上面的处理之后字符串的长度为0,我们就可以人为的令字符串的长度为1,a[0]=0,b[0]=0.然后进行转化,转化的时候一般有两种方法比较容易想到一是在后面-‘0’,另一种是在后面-48,不过看发帖说‘0’-‘0’=‘\0’(自己理解是因为两个字符是一样的,所以减完之后就是空了),所以还是用第二种方法进行倒序的转换。这里对于减法需要注意,为了是最后的‘-’比较好处理,所以我们要用大数减去小数,在做转换的时候,如果a<b,那么就需要做相应的处理可以再转化数组的时候将大的数组放进规定的放大数的数组里,并做好标记;也可以直接转化,然后在减的时候用表示大数的数组减去表示小数的数组,并做标记)。注意在每次调用函数的时候都要将自己定义的三个整形数组清0.

然后就是计算了,对于加法,按照竖式计算的顺序每一位的两个数相加,相加的结果存入c[i]里面,如果c[i]>9,则c[i+1]++;c[i]+=10;这样循环着计算(循环的长度是两个数组里面最长的数组的长度),最后计算完了之后要判断c[length](length表示两个数组里面最长的数组的长度)是否等于1,即判断最高位是否有进位,如果有那么length++。对于减法,思路和加法一样,按照竖式计算的顺序每一位的两个数相减,相减的结果存入c[i]里面,如果如果c[i]<0,则c[i+1] - -;c[i]+=10;这样循环着计算(循环的长度是两个数组里面最长的数组的长度),最后计算完了之后要判断数组a的前面(length表示两个数组里面最长的数组的长度)是否有等于0的位,即判断前面的位是否被借走,剩下0,如果是那么length--,终止的条件是c[length--]!=0(就是所说的退位)。

最后就是将整形数组c中的数字转换为字符串,即每个位上的数+48.要注意减法中如果最后的结果是负数的时候要在数组的前面加‘-’,因为最后是‘%s’输出的,所以可以领cc[0]=’-’.还要注意在转换完成的时候要在字符数组的最后加上‘\0’,这样可以防止由于数组没有初始化而导致输出乱码。


实现代码

<span style="font-family:Microsoft YaHei;font-size:14px;">void plus(char *a, char *b, char *c)
{
	int lengtha,lengthb,length;
	int i,j;
	int aa[505],bb[505],cc[505];
    for(i=0;i<505;i++)
    {
    	aa[i]=0;
    	bb[i]=0;
    	cc[i]=0;
    }
	while(a[0]=='0')a++;
	while(b[0]=='0')b++;
	lengtha=strlen(a);
	lengthb=strlen(b);
	
	if(lengtha==0&&lengthb!=0)
	{
		length=lengthb;
		aa[0]=0;
	}
	else if(lengtha!=0&&lengthb==0)
	{
		length=lengtha;
		bb[0]=0;	
	}
	else if(lengtha==0&&lengthb==0)
	{
		length=1;
		aa[0]=0;
		bb[0]=0;
	}
	else if(lengtha>lengthb)
	{
		length=lengtha;     //找出最长的数 
	}
	else
	{
		length=lengthb;
	}
	for(i=0;i<lengtha;i++)
	{
		aa[i]=a[lengtha-1-i]-48;	
	}
	for(i=0;i<lengthb;i++)              //转换字符串为整形数组 
	{
		bb[i]=b[lengthb-1-i]-48;
	}
	for(i=0;i<length;i++)
	{
		cc[i]+=aa[i]+bb[i];
		if(cc[i]>9)                //计算 
		{
			cc[i+1]++;
			cc[i]-=10;
		}
	} 
	if(cc[length]>0)
	{
		length++;
	}
	for(j=0;j<length;j++)
	{
		c[j]=cc[length-1-j]+48;	
	} 
	c[length]='\0';
} 

void minus(char *a, char *b, char *c)
{
	int lengtha,lengthb,length;
	int i,j,temp=0,temp2;
	int aa[505],bb[505],cc[505];
	for(i=0;i<505;i++)
	{
		aa[i]=0;
		bb[i]=0;
		cc[i]=0;
	}
	temp=0;
	while(a[0]=='0')a++;
	while(b[0]=='0')b++;
	lengtha=strlen(a);
	lengthb=strlen(b);
	
	if(lengtha!=0&&lengthb==0)
	{
		length=lengtha;
		bb[0]=0;
	}
	else if(lengthb!=0&&lengtha==0)
	{
		length=lengthb;
		aa[0]=0;
	}
	else if(lengtha==0&&lengthb==0)
	{
		length=1;
		aa[0]=0;
		bb[0]=0;
	} 
	else if(lengtha==lengthb)
	{
		length=lengtha;
		temp2=strcmp(a,b);
		if(temp2<0)
		{
			temp=2;
		}
	}
	else if(lengthb>lengtha)
	{
		length=lengthb;
		temp=1;
	}
	else
	{
		length=lengtha;
	}
	
	if(temp!=0)
	{
		for(i=0;i<lengthb;i++)
		{
			aa[i]=b[lengthb-1-i]-48; 
		}
		for(i=0;i<lengtha;i++)
		{
			bb[i]=a[lengtha-1-i]-48;
		} 
	}
	else
	{
		for(i=0;i<lengtha;i++)
		{
			aa[i]=a[lengtha-1-i]-48;
		}
		for(i=0;i<lengthb;i++)
		{
			bb[i]=b[lengthb-1-i]-48;
		}
	}
		
	for(j=0;j<length;j++)
	{
		cc[j]+=aa[j]-bb[j];
		if(cc[j]<0)
		{                     
			cc[j+1]--;
			cc[j]+=10;
		}
	}
	while(cc[length]==0&length>0)
	{
		length--;
	}
	length++;
	
	if(temp==0)
	{
		for(i=0;i<length;i++)
		{
			c[i]=cc[length-1-i]+48;
		}
		c[length]='\0';
	}
	else
	{
		c[0]='-';
		for(i=1;i<=length;i++)
		{                    
			c[i]=cc[length-i]+48;
		}
		c[length+1]='\0';
	}		
}</span>


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值