大正数减法(华为2013校园招聘上机笔试题 )

问题描述:    
两个任意长度的正数相减,这两个正数可以带小数点,也可以是整数,请输出结果。 输入的字符串中,不会出现除了数字与小数点以外的其它字符,不会出现多个小数点以及小数点在第一个字符的位置等非法情况,所以考生的程序中无须考虑输入的数值字符串非法的情况。 
详细要求以及约束:
1.输入均为正数,但输出可能为负数; 
2.输入输出均为字符串形式;
3.如果输出是正数则不需要带符号,如果为负数,则输出的结果字符串需要带负号
例如:2.2-1.1 直接输出为“1.1”,1.1-2.2 则需要输出为“-1.1”
 4.输出的结果字符串需要过滤掉整数位前以及小数位后无效的0,小数位为全0的,直接输出整数位
例如相减结果为11.345,此数值前后均不可以带0,“011.345”或者“0011.34500”等等前后带无效0的均视为错误 输出。例如1.1-1.1结果为0.0,则直接输出0。
要求实现函数:
void Decrease(char *input1, char*input2, char *output)
【输入】 char *iinput1 被减数
char*nput2 减数 
【输出】 char *output 减法结果
【返回】 无
示例
输入:char *input1="2.2" 
char *input2="1.1"
输出:char*output="1.1"
输入:char *input1="1.1" 
char *input2="2.2"
输出:char *output="-1.1"

以上摘自 http://blog.csdn.net/lanyan822/article/details/7983832 ,但是考虑到没有给出这个的源代码,自己随手写了一个,写得不好,仅供娱乐,欢迎大神指点。

 

 

这次的代码很长,我是为了写的可读性更高一点,很多地方比较累赘而且用的方法比较直接,也是我一开始直接想到的。如果有更好的方法希望大家提供哈...

//正数减法
//问题描述:    
//两个任意长度的正数相减,这两个正数可以带小数点,也可以是整数,请输出结果。
//输入的字符串中,不会出现除了数字与小数点以外的其它字符,不会出现多个小数点以及小数点在第一个字符的位置等非法情况,所以考生的程序中无须考虑输入的数值字符串非法的情况。 
//详细要求以及约束:
//1.输入均为正数,但输出可能为负数; 
//2.输入输出均为字符串形式;
//3.如果输出是正数则不需要带符号,如果为负数,则输出的结果字符串需要带负号
//例如:2.2-1.1 直接输出为“1.1”,1.1-2.2 则需要输出为“-1.1”
// 4.输出的结果字符串需要过滤掉整数位前以及小数位后无效的0,小数位为全0的,直接输出整数位
//例如相减结果为11.345,此数值前后均不可以带0,“011.345”或者“0011.34500”等等前后带无效0的均视为错误 输出。例如1.1-1.1结果为0.0,则直接输出0。
//要求实现函数:
//void Decrease(char *input1, char*input2, char *output)
//【输入】 char *iinput1 被减数
//char*nput2 减数 
//【输出】 char *output 减法结果
//【返回】 无
//示例
//输入:char *input1="2.2" 
//char *input2="1.1"
//输出:char*output="1.1"
//输入:char *input1="1.1" 
//char *input2="2.2"
//输出:char *output="-1.1"
#include <algorithm>
#include <assert.h>
//得到小数点的位置
int getDot(char *input1)//小数点计算函数
{
	return find(input1,input1+strlen(input1),'.') - input1;
}

void Decrease(char *input1, char*input2, char *output)
{
	assert(input1 != NULL && input2 != NULL && output != NULL);//假设三个参数都不为空
//1.小数点对其
	int dot1 = getDot(input1),dot2 = getDot(input2);
//2.小数点对其初始化两个char数组,方便之后运算。长度为双方可能的最大位数
	int length = ((strlen(input1)-dot1)>(strlen(input2)-dot2)?(strlen(input1)-dot1):(strlen(input2)-dot2))/*小数部分最长的值*/
		+(dot1>dot2?dot1:dot2)/*整数部分最长的值*/+1/*可能产生的符号位与小数点*/;
	char *str1,*str2,*result;

	str1 = (char *)malloc(length+1);//加1为了存结束符
	str2 = (char *)malloc(length+1);
	result = (char *)malloc(length+1);

	memset(str1,'0',length);
	memset(str2,'0',length);
	memset(result,'0',length);

	str1[length] = '\0';
	str2[length] = '\0';
	result[length] = '\0';

//3.得出每个字符串小数点对其后的位置,但是不拷贝最后一个'\0'结束符
	memcpy(&str1[abs(dot1>dot2?dot1:dot2-dot1)+1],input1,strlen(input1));
	memcpy(&str2[abs(dot1>dot2?dot1:dot2-dot2)+1],input2,strlen(input2));

	
//4.得到两数之间较大的数,为了保证始终大数减小数,省的借位情况复杂
	int isPlus = true;//如果被减数更大则为真
	char *max = str1,*min = str2;
	for(int i = 1;i < length;++i)
	{
		if(str1[i] > str2[i])
		{
			max = str1;
			min = str2;
			break;
		}
		else if(str1[i] < str2[i])
		{
			isPlus = false;
			max = str2;
			min = str1;
			break;
		}
		else if(i == length - 1)
		{//两个字符串数字相等
			output[0] = '0';
			output[1] = '\0';
			return ;
		}
	}
	//把没有小数点的全部补齐
	result[dot1>dot2?dot1:dot2 + 1] = '.';
	max[dot1>dot2?dot1:dot2 + 1] = '.';
	min[dot1>dot2?dot1:dot2 + 1] = '.';
//5.开始运算
	for(int i = length-1;i > 0;--i)
	{//开始从右到左开始减
		if(max[i] == '.')
		{
			result[i] == '.';
			continue;
		}
		int temp;
		temp = max[i] - min[i];
		if(temp < 0)
		{//如果不够减时向高位借数
			int j = i;
			while(max[j] == '0' || max[j] == '.'/* && j != 0*/)
			{//找到可以借位的数为止,因为输入的都是整数,所以不做更多讨论
				if(max[j] == '0')
				{
					max[j] = '9';
				}
				j--;
			}
			max[j]--;
			temp += 10;
		}
		result[i] = temp + '0';
	}
	if(!isPlus)
		output[0] = '-';
//6.把结果字符格式化给output字符串
	for(unsigned int i = strlen(result);i >= 0;++i)
	{//清除末尾0或最后一位是小数点
		if(result[i] == '0' || result[i] == '.')
			result[i] = '\0';
		else
			break;
	}
	unsigned int first = 1;//记录第一位有效位的起始位置
	while(result[first] == '0')
	{
		first++;
	}
	strcpy(output,&result[first]);
}

int _tmain(int argc, _TCHAR* argv[])
{
	char r[10000];
	Decrease("2.2", "1.1",r);
	cout<<r;
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值