pat乙级 1034 有理数四则运算 (20 分)

本题要求编写程序,计算 2 个有理数的和、差、积、商。

输入格式:
输入在一行中按照 a1/b1 a2/b2 的格式给出两个分数形式的有理数,其中分子和分母全是整型范围内的整数,负号只可能出现在分子前,分母不为 0。

输出格式:
分别在 4 行中按照 有理数1 运算符 有理数2 = 结果 的格式顺序输出 2 个有理数的和、差、积、商。注意输出的每个有理数必须是该有理数的最简形式 k a/b,其中 k 是整数部分,a/b 是最简分数部分;若为负数,则须加括号;若除法分母为 0,则输出 Inf。题目保证正确的输出中没有超过整型范围的整数。

输入样例 1:
2/3 -4/2
输出样例 1:
2/3 + (-2) = (-1 1/3)
2/3 - (-2) = 2 2/3
2/3 * (-2) = (-1 1/3)
2/3 / (-2) = (-1/3)
输入样例 2:
5/3 0/6
输出样例 2:
1 2/3 + 0 = 1 2/3
1 2/3 - 0 = 1 2/3
1 2/3 * 0 = 0
1 2/3 / 0 = Inf

原题链接:https://pintia.cn/problem-sets/994805260223102976/problems/994805287624491008

思路:此题还是有一定难度的。首先要搞清楚分数的几种形式:真分数(分子小于分母),假分数(分子大于分母的分数),最简分数(分子和分母不可再约分),带分数(几又几分之几的形式,例如:1 1/2等)。然后编程按题目要求的格式输出。
本题考察的知识点:
1.求两个数的最大公约数:辗转相除法,有模板代码,捋一遍思路记住即可,下次要会用。侧面说明了数学对于计算机来说是非常重要的!!!
2.格式化数据输入和输出。比如题目中要求的:正负号的处理,一些特殊符号输出(空格,"()",等);


#include 
using namespace std;
typedef long long ll;

ll gcd(ll a,ll b);	
void cvt(ll x,ll y);

int main()
{
	ll a,b,c,d;
	while(scanf("%lld/%lld%lld/%lld",&a,&b,&c,&d)==4)
	{
		cvt(a,b);printf(" + ");cvt(c,d);printf(" = ");cvt(a*d+b*c,b*d);printf("\n");
		cvt(a,b);printf(" - ");cvt(c,d);printf(" = ");cvt(a*d-b*c,b*d);printf("\n");
		cvt(a,b);printf(" * ");cvt(c,d);printf(" = ");cvt(a*c,b*d);printf("\n");
		cvt(a,b);printf(" / ");cvt(c,d);printf(" = ");cvt(a*d,b*c);printf("\n");
		
	}
	return 0;
}

ll gcd(ll a,ll b)
{//求两个数的最大公约数 
	if(b==0)
		return a;
	else
		return gcd(b,a%b);
}

void cvt(ll x,ll y)
{
	//1.有一个数为0,退出 
	if(x*y==0)
	{
		printf("%s",y==0?"Inf":"0");
		return ;
	}
	//2.判断正负号,真假分数的化解 
	bool flag = (x<0&&y>0)||(y<0&&x>0);//flag:负号标记位 
	printf("%s",flag?"(-":"");
	x = abs(x);
	y = abs(y);
	if(x%y==0)
	{
		printf("%lld%s",x/y,flag?")":"");
		return;
	}
	ll pa = 0;
	//化成最简分数 
	ll m = gcd(x,y);
	x /= m;
	y /= m;	
	if(x>y)
	{//化成带分数 
		pa = x/y;
		x = x%y;
	} 	
	if(pa>0)
	{
		printf("%lld",pa);		
	}
	if(pa&&x)
	{
		printf(" ");
	}
	printf("%lld/%lld%s",x,y,flag?")":"");
}

你可能感兴趣的:(pat乙级真题)