PAT 乙级 1034 有理数四则运算 v0.8
1. 题目简述及在线测试位置
1.1 将两个有理数的四则运算代码化
1.2 在线测试位置:PAT 1034 有理数四则运算
2. 基本思路
2.1 有理数 可以看成 两个整数之比。进行加法和减法运算时,分母若不相同,需要先进行通分;进行乘法运算时,分子分母分别相乘;进行除法运算,可以看成 数1 与 数2的倒数 相乘。代码据此实现即可
2.2 题目要求:输出的每个有理数必须是该有理数的最简形式 k a/b ,若 c/b = k a/b,那么 k = c 除 d、a = c 模 b
2.3 有两点需要注意:(1)虽然题目中注明 分子和分母全是整型范围内的整数,但是 两个整数 相乘 可能超过整型范围,因此运算结果需要通过 long long 类型存储 (2)题目要求输出最简分数部分,因此我们需要先找出 分子 分母的最大公约数,求最大公约数的算法需要控制时间复杂度
2.4 题目的输出格式较复杂,可以按示例进行调测
3. 完整AC代码
#include <iostream>
#include<cmath>
using namespace std;
#define MAX 100
void PrintRema(int Quotient,int Remainer, long long Denominator);
void PrintQuot(int Quotient, int Remainer);
void Arithmetic(int Nume01, int Deno01, int Nume02, long long Deno02,char Symbol);
//Greatest Common Divisor
int GCD(long long a, long long b)//辗转相除法
{
long long z = b, x=abs(a),y=b;
if (!z)
return 1;
while (x % y != 0)
{
z = x % y;
x = y;
y = z;
}
return z;
}
int main()
{
string N1, N2;
int Numerator01, Numerator02, Denominator01, Denominator02;
char Symbol;
int Gcd;
//分子是整数:负数 0 正数 //输入示例 2/3 -4/2
scanf("%d/%d %d/%d", &Numerator01, &Denominator01, &Numerator02, &Denominator02);
if (Numerator01) //对分数进行化简,消去最大公约数
{
Gcd = GCD(Numerator01, Denominator01);
Numerator01 /= Gcd;
Denominator01 /= Gcd;
}
if (Numerator02)
{
Gcd = GCD(Numerator02, Denominator02);
Numerator02 /= Gcd;
Denominator02 /= Gcd;
}
Symbol = '+';
Arithmetic(Numerator01, Denominator01, Numerator02, Denominator02,Symbol);
cout << endl;
Symbol = '-';
Arithmetic(Numerator01, Denominator01, Numerator02, Denominator02, Symbol);
cout << endl;
Symbol = '*';
Arithmetic(Numerator01, Denominator01, Numerator02, Denominator02, Symbol);
cout << endl;
Symbol = '/';
Arithmetic(Numerator01, Denominator01, Numerator02, Denominator02, Symbol);
return 0;
}
void Arithmetic(int Nume01, int Deno01, int Nume02, long long Deno02, char Symbol)
{
long long NumeResult,DenoResult; //测试点:乘除的运算可能超过整数范围,因此运算结果用long long 存储
int Quot_Result, Rema_Result;
int Quotient01, Quotient02, Remainer01, Remainer02;
Quotient01 = Nume01 / Deno01;
Remainer01 = Nume01 % Deno01;
Quotient02 = Nume02 / Deno02;
Remainer02 = Nume02 % Deno02;
if (Symbol == '+')
{
if (Deno01 == Deno02)//
{
NumeResult = Nume01 + Nume02;
DenoResult = Deno01;
}
else
{
DenoResult = Deno01 * Deno02;
NumeResult = (Nume01 * Deno02) + (Nume02 * Deno01);
}
Quot_Result = NumeResult / DenoResult;
Rema_Result = NumeResult % DenoResult;
}
else if (Symbol == '-')
{
if (Deno01 == Deno02)//
{
NumeResult = Nume01 - Nume02;
DenoResult = Deno01;
}
else
{
DenoResult = Deno01 * Deno02;
NumeResult = (Nume01 * Deno02) - (Nume02 * Deno01);
}
Quot_Result = NumeResult / DenoResult;
Rema_Result = NumeResult % DenoResult;
}
else if (Symbol == '*')
{
NumeResult = (long long )Nume01 * Nume02; //测试点:两数相乘可能超过整数的范围
DenoResult = (long long)Deno01 * Deno02;
Quot_Result = NumeResult / DenoResult;
Rema_Result = NumeResult % DenoResult;
}
else if (Symbol == '/')
{
if (Nume02 == 0)
{
PrintQuot(Quotient01, Remainer01);
PrintRema(Quotient01, Remainer01, Deno01);
cout << " / 0 = Inf";
return;
}
else if (Nume02 < 0)
{
//负号只可能出现在分子前 //由于是除法,交换符号的位置
NumeResult = (long long )Nume01 * Deno02 * -1;
DenoResult = (long long )Deno01 * Nume02 * -1;
}
else if(Nume02>0)
{
NumeResult = (long long)Nume01 * Deno02; //测试点:两数相乘可能超过整数的范围,所以用 long long
DenoResult = (long long)Deno01 * Nume02;
}
Quot_Result = NumeResult / DenoResult;
Rema_Result = NumeResult % DenoResult;
}
PrintQuot(Quotient01, Remainer01);
PrintRema(Quotient01,Remainer01, Deno01);
if (Symbol == '+')
cout << " + ";
else if (Symbol == '-')
cout << " - ";
else if (Symbol == '*')
cout << " * ";
else if (Symbol == '/')
cout << " / ";
PrintQuot(Quotient02,Remainer02);
PrintRema(Quotient02,Remainer02, Deno02);
cout << " = ";
PrintQuot(Quot_Result, Rema_Result);
PrintRema(Quot_Result,Rema_Result, DenoResult);
return;
}
void PrintRema(int Quotient, int Remainer, long long Denominator)
{
int Gcd=1;
long long Rema = Remainer, Deno = Denominator;
Gcd = GCD(Remainer, Denominator);
Rema /= Gcd;
Deno /= Gcd;
if (!Remainer);
else if (Remainer > 0)
cout << Rema << "/" << Deno;
else if (Remainer < 0 && Quotient)
cout << Rema*-1 << "/" << Deno << ")"; //负号已经打印过了
else if (Remainer < 0 && !Quotient)
cout << "(" << Rema << "/" << Deno << ")";
}
void PrintQuot(int Quotient, int Remainer)
{
if (!Quotient && Remainer);
else if (!Quotient && !Remainer)
cout << "0";
else if(Quotient <0 && Remainer)
cout <<"("<< Quotient <<" ";
else if (Quotient < 0 && !Remainer)
cout << "(" << Quotient << ")";
else if(Quotient > 0 && Remainer)
cout << Quotient << " ";
else if (Quotient > 0 && !Remainer)
cout << Quotient;
}