PAT Basic Level 1034 有理数四则运算 解题思路及AC代码

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值