电子协会编程C语言指导教师培训——实数加法

48:实数加法
描述
求两个实数相加的和。
题目中输入输出里出现的浮点数都有如下的形式:
P1P2...Pi.Q1Q2...Qj。对于整数部分,P1P2...Pi是一个非负整数且当整数部分不为0时,P1不等于0;对于小数部分,Qj不等于0。
输入
2行,每行是一个加数。每个加数的长度不超过100。
输出
一行,即相应的和。输出保证一定是一个小数部分不为0的实数。
样例输入1
0.111111111111111111111111111111
0.111111111111111111111111111111
样例输出1
0.222222222222222222222222222222

样例输入2
345.9
777.999
样例输出2
1123.899

样例输入3
123.25
1.25
样例输入3
124.5

思路解析:题目整体难度不大,代码写起来很繁琐,处理细节问题也比较多。字符串读入,分成小数点前部分和小数点后部分,分别进行高精度加法运算,注意小数点后部分向小数点前部分的进位问题,小数点后部分要处理末尾的零。

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
#define N 105
char a[N],b[N];
int a1[N]={0},a2[N]={0};
int b1[N]={0},b2[N]={0};
int fj(char a[],int a1[],int a2[])
{
	int len=0;
	while(a[len]!='.')len++;
	int i,j;
	for(i=1,j=len-1;j>=0;i++,j--){
		a1[i]=a[j]-'0';
	}
	int lenl=strlen(a);
	for(i=1,j=len+1;j<lenl;i++,j++){
		a2[i]=a[j]-'0';
	}
	return len;
}
int xjia1(int a[],int b[],int len1,int len2)
{
	int i=1,jw=0;
	int lenll=max(len1,len2);
	while(i<=lenll){
		a[i]+=b[i]+jw;
		if(a[i]>=10){
			jw=1;
			a[i]%=10;
		}
		else jw=0;
		i++;	
	}
	if(jw>0){
		a[i]+=1;
		lenll++;
	}
	return lenll;
}
int xjia2(int a[],int b[],int len1,int len2)
{
	int jw=0;
	int i=max(len1,len2);	
	while(i>=1){
		a[i]+=b[i]+jw;
		if(a[i]>=10){
			jw=1;
			a[i]%=10;
		}
		else jw=0;
		i--;	
	}
	if(jw>0){
		a[i]+=1;
	}
	return max(len1,len2);
}
int main(int argc, char *argv[])
{
	cin>>a>>b;
	int lena1=fj(a,a1,a2);
	int lena2=strlen(a)-lena1-1;
	int lenb1=fj(b,b1,b2);
	int lenb2=strlen(b)-lenb1-1;
	
	int len1=xjia1(a1,b1,lena1,lenb1);
	int len2=xjia2(a2,b2,lena2,lenb2);
	if(a2[0]>0)a1[1]+=1;
	for(int i=len1;i>=1;i--)cout<<a1[i];
	cout<<".";
	while(a2[len2]==0)len2--;
	for(int i=1;i<=len2;i++)cout<<a2[i];
	cout<<endl;
	return 0;
}
//纯面向对象实现
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
class RealNumber
{
public:
	RealNumber():m_number(""),m_left(""),m_right(""){}
	RealNumber(const char* data)
	{
		m_number=data;
		int pos = m_number.find_first_of(".");
		if(pos>=0)
		{
			m_left = m_number.substr(0,pos);
			m_right=m_number.substr(pos+1);
		}
		else
			m_left =m_number;
	}
	
	RealNumber& operator =(const char* data)
	{
		RealNumber t(data);
		*this = t;
		return *this;
	}
	
	RealNumber operator +(const RealNumber &num)
	{
		RealNumber a=*this,b=num,c;
		add_left(a.m_left,b.m_left,c.m_left);
		int p=add_right(a.m_right,b.m_right,c.m_right);
		if(p)
			add_left(c.m_left,string(1,'0'+p),c.m_left);
		if(c.m_right.length())
			c.m_number = c.m_left +"."+c.m_right;
		else
			c.m_number = c.m_left;
		return c;
	}
	
	friend ostream& operator <<(ostream &os,const RealNumber &num)
	{
		os<<num.m_number;
		return os;
	}
	friend istream& operator >>(istream &is,RealNumber &num)
	{
		string t;
		is>>t;
		num=t.c_str();
		return is;
	}
private:
	int add_right(string a,string b,string &c)
	{
		//补齐长度 
		if(a.length()>b.length())
			b.append(a.length()-b.length(),'0');
		else if(a.length()<b.length())
			a.append(b.length()-a.length(),'0');
		c = string(a.length(),'0');
		//逆序
		reverse(a.begin(),a.end());
		reverse(b.begin(),b.end());
		int i,p=0;
		for(i=0;i<a.length();i++)
		{
			c[i]=p+a[i]+b[i]-'0';
			p=0;
			if(c[i]>'9')
			{
				c[i]-=10;
				p=1;
			}
		} 
		//去掉0
		while(c.length())
		{
			if(*c.begin()=='0')
				c.erase(c.begin());
			else
				break;
		}
		//结果逆序
		reverse(c.begin(),c.end());
		return p;
	}	
	void add_left(string a,string b,string &c)
	{
		//逆序
		reverse(a.begin(),a.end());
		reverse(b.begin(),b.end());
		//补齐长度 
		if(a.length()>b.length())
			b.append(a.length()-b.length(),'0');
		else if(a.length()<b.length())
			a.append(b.length()-a.length(),'0');
		c = string(a.length(),'0');
		int p=0;
		for(int i=0;i<a.length();i++)
		{
			c[i]=p+a[i]+b[i]-'0';
			p=0;
			if(c[i]>'9')
			{
				c[i]-=10;
				p=1;
			}
		} 
		if(p)
			c.append(1,'0'+p);
		//结果逆序
		reverse(c.begin(),c.end());
	}
private:
	string m_number;
	string m_left;
	string m_right;
};

using namespace std;
int main(int argc, char *argv[])
{
	RealNumber r1,r2;
	cin>>r1>>r2;
	cout<<(r1+r2)<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宏阳李老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值