本题要求编写程序,计算 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 = In
1、解题思路
本题涉及到分数的化简、运算和输出。
(1)遇到分数问题,通常将分子分母分开处理,定义分数结构体:
struct Fraction{
//由于分数的乘法和除法的过程可能是分子或分母超过int型使用范围,所以一般情况下,分子和分母都是用long long型来存储
long long up;//分子
long long down;//分母
}
(2)分数问题肯定会遇到化简问题,首先是看分子、分母是否有公约数,有则约去最大公约数:
int gcd(int a,int b){
//欧几里得算法
if(b==0) return a;//0和任意一个整数a的最大公约数都是a
else return gcd(b,a%b);//a和b的公约数也是b和a%b的公约数
}
化简步骤:
1.若分数为负,负号必须跟着分子,分母始终为正;
2.若分子为0,令分母为1;
3.约分:求出分子的绝对值和分母的绝对值之间的最大公约数d,令分子分母同时除以d。
Fraction reduction(Fraction result){
if(result.down<0){
result.up=-result.up;
result.down=-result.down;
}else if(result.up==0){
result.down=1;
}else{
int d=gcd(abs(result.up),abs(result.down));
result.up/=d;
result.down/=d;
}
return result;
}
(3)分数的四则运算可以按照数学计算方式解决,主要求计算后结果的分子和分母:
Fraction Add(Fraction a,Fraction b){//加法
Fraction result;
result.up=a.up*b.down+a.down*b.up;
result.down=a.down*b.down;
return reduction(result);
}
Fraction Minute(Fraction a,Fraction b){//减法
Fraction result;
result.up=a.up*b.down-a.down*b.up;
result.down=a.down*b.down;
return reduction(result);
}
Fraction Multi(Fraction a,Fraction b){//乘法
Fraction result;
result.up=a.up*b.up;
result.down=a.down*b.down;
return reduction(result);
}
Fraction divide(Fraction a,Fraction b){//除法
Fraction result;
result.up=a.up*b.down;
result.down=a.down*b.up;
return reduction(result);
}
(3)分数的输出:
1.输出分数前,要先进行化简;
2.若分母为1,则说明是个正整数,直接输出即可
3.若分子的绝对值大于分母的绝对值,则分数为假分数,此时应按带分数的形式输出,整数部分为r.up/r.down,小数部分分母为r.up%r.down,分母为r.down。
4.若分数为真分数,直接输出分子和分母:
void showResult(Fraction r){
r=reduction(r);
if(r.up<0) printf("(");
if(r.down==1)printf("%d",r.up);
else if(abs(r.up)>r.down){
printf("%d %d/%d",r.up/r.down,abs(r.up)%r.down,r.down);
}else {
printf("%d/%d",r.up,r.down);
}
if(r.up<0)printf(")");
}
根据题意,负分数前后要使用括号,分母为0,要输出Inf,代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){//求公约数
if(b==0) return a;
else return gcd(b,a%b);
}
struct Fraction{
ll up;//分子
ll down;//分母
};
Fraction reduction(Fraction result){
if(result.down<0){
result.up=-result.up;
result.down=-result.down;
}else if(result.up==0){
result.down=1;
}else{
int d=gcd(abs(result.up),abs(result.down));
result.up/=d;
result.down/=d;
}
return result;
}
Fraction Add(Fraction a,Fraction b){
Fraction result;
result.up=a.up*b.down+a.down*b.up;
result.down=a.down*b.down;
return reduction(result);
}
Fraction Minute(Fraction a,Fraction b){
Fraction result;
result.up=a.up*b.down-a.down*b.up;
result.down=a.down*b.down;
return reduction(result);
}
Fraction Multi(Fraction a,Fraction b){
Fraction result;
result.up=a.up*b.up;
result.down=a.down*b.down;
return reduction(result);
}
Fraction divide(Fraction a,Fraction b){
Fraction result;
result.up=a.up*b.down;
result.down=a.down*b.up;
return reduction(result);
}
void showResult(Fraction r){
r=reduction(r);
if(r.up<0) printf("(");
if(r.down==1)printf("%d",r.up);
else if(abs(r.up)>r.down){
printf("%d %d/%d",r.up/r.down,abs(r.up)%r.down,r.down);
}else {
printf("%d/%d",r.up,r.down);
}
if(r.up<0)printf(")");
}
int main(){
Fraction a,b;
scanf("%lld/%lld %lld/%lld",&a.up,&a.down,&b.up,&b.down);
//和
showResult(a);
printf(" + ");
showResult(b);
printf(" = ");
showResult(Add(a,b));
printf("\n");
//差
showResult(a);
printf(" - ");
showResult(b);
printf(" = ");
showResult(Minute(a,b));
printf("\n");
//积
showResult(a);
printf(" * ");
showResult(b);
printf(" = ");
showResult(Multi(a,b));
printf("\n");
//商
showResult(a);
printf(" / ");
showResult(b);
printf(" = ");
if(b.up==0)printf("Inf");
else {
showResult(divide(a,b));
}
return 0;
}
2、总结
1、初次接触涉及分数的题目,知识点掌握得不是很全面,上面列出的关于分数的代码可以在任何涉及分数的题目中套用。
2、分数除法中,判断除数是否为0,只需要判断除数的分子是否为0。
3、由于分数的乘法和除法的过程可能是分子或分母超过int型使用范围,所以一般情况下,分子和分母都是用long long型来存储。
4、判断分子是否大于分母时,一定要使用分子的绝对值,应为分母一直为整数,而分子可能为负数。