题目 有理数四则运算
本题要求编写程序,计算 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
这个题真真实实卡了一下午,先是一直报浮点错误,然后测试点3又卡着说答案错误,写一下下午踩的坑。
首先这个题的思路还是很简单的,我用的通分求的加减乘除,加个循环后面switch一下也可,8过需要注意的是输出的不仅是k a/b的形式,而且a/b还必须是最简形式,所以需要求出最大公约数,用辗转相除求一下就行(普通循环会有超时)。
然后坑就出现了,题目上说了一句:
“题目保证正确的输出中没有超过整型范围的整数”
然而,这并不能保证在计算过程中不会有超出整型范围的整数。
所以,通分的时候一定要注意加上long long才行,不然就会答案错误。
以及,最后发现其实可以直接定义输入都是long long类型的,就不需要后面再打括号写了,就是得这样输入,完整的代码在后面懒得改了:
long long a1, b1, a2, b2;
scanf("%lld/%lld %lld/%lld", &a1, &b1, &a2, &b2);
然后就是浮点错误,搜了一下别人的有说PTA用abs会报浮点错误,我用了没有。
浮点错误主要是因为分母有0:
比如10和0求得的最大公约数如果为0,再给他来一个约分就肯定会报错,所以算的时候要么保证最大公约数不为0要么就为0的话特殊处理一下,就能保证k a/b(我用的fraction函数)里面b的值约分之后仍然不为0。
再然后就是除法的时候需要考虑一下,如果a2为0(题目规定b1、b2不为0)的话输出Inf。
最后需要注意一下负号和括号的处理,基本上就没有问题了。
大概就这些,愿这个世界没有bug
代码
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
// 输出最大公约数
long long gcd(long long a, long long b)
{
if (a < b)
a, b = b, a; // a为大数,b为小数
while (a%b != 0) // 辗转相除
{
long long temp = a%b;
a = b;
b = temp;
}
return b;
}
// 输出k a/b格式
void fraction(long long a,long long b)
{
if (a<0|| b<0)
cout << "(-";
if (a%b == 0)
{
cout << abs(a / b);
}
else
{
if (a / b != 0)
cout << abs(a / b) << " ";
cout << abs(a%b) << "/" << abs(b);
}
if (a<0||b<0)
cout << ")";
}
int main()
{
int a1, b1, a2, b2;
scanf("%d/%d %d/%d", &a1, &b1, &a2, &b2);
int gcd1 = gcd(a1, b1);
int gcd2 = gcd(a2, b2);
int g;
// 加法
fraction(a1 / gcd1, b1 / gcd1);
cout << " + ";
fraction(a2 / gcd2, b2 / gcd2);
cout << " = ";
long long num = (long long)a1*b2 + (long long)a2*b1;
long long den = (long long)b1*b2;
g = gcd(num,den);
fraction(num / g, den / g);
cout << "\n";
// 减法
fraction(a1 / gcd1, b1 / gcd1);
cout << " - ";
fraction(a2 / gcd2, b2 / gcd2);
cout << " = ";
num = (long long)a1*b2 - (long long)a2*b1;
den = (long long)b1*b2;
g = gcd(num, den);
fraction(num / g, den / g);
cout << "\n";
// 乘法
fraction(a1 / gcd1, b1 / gcd1);
cout << " * ";
fraction(a2 / gcd2, b2 / gcd2);
cout << " = ";
num = (long long)a1*a2;
den = (long long)b1*b2;
g = gcd(num, den);
fraction(num / g, den / g);
cout << "\n";
// 除法
fraction(a1 / gcd1, b1 / gcd1);
cout << " / ";
fraction(a2 / gcd2, b2 / gcd2);
cout << " = ";
if (a2 == 0)
cout << "Inf";
else
{
num = (long long)a1*b2;
den = (long long)b1*a2;
g = gcd(num, den);
fraction(num / g, den / g);
}
}