您的位置:首页 > 其它

PAT 1034 有理数四则运算(20)

2015-02-25 23:07 211 查看

题目

/*
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
*/

思路

// 1/2 + 4/5 =
// 如何把一个数化为最简分数?
// ::先化为真分数,再分子与分母的最大公约数
// 如何进行分数运算?
// ::分母通分(求最小公倍数),分子加成

代码

#include <iostream>
#include <stdio.h>

using namespace std;

long long maxCommon(long long a, long long b){
if(b == 0) return a;
else return maxCommon(b, a%b);
}

struct DivNum{
bool positive;
bool extInt;
bool extDiv;
long long int integer; //整数部分
long long int divChild;
long long int divMum;
bool isSimple;//是否已经化简

DivNum(){
positive = false;
extInt = false;
extDiv = false;

integer = 0;
divChild = 0;
divMum = 0;

isSimple = false;
}

void in(char * str){

string num = str;
if(str[0] == '-'){
num.erase(0,1);
}else{
positive = true;
}
sscanf(num.c_str(),"%lld/%lld", &divChild, &divMum);
}
void simplify(){
if(divMum == 0)return;

// 分子为0
if(divChild == 0) {
extInt = true;
extDiv = false;
integer = 0;
positive = true;
return;
}

extDiv = true;

// 假分数
if(divChild >= divMum){
extInt = true;
integer = divChild / divMum;
divChild = divChild % divMum;

//
if(divChild == 0) extDiv = false;
}

// 化为最简真分数
long long common = maxCommon(divChild, divMum);
if(common == 0) return;
divChild /= common;
divMum /= common;

}

friend DivNum operator +(const DivNum &a, const DivNum &b){
DivNum res;

// 一正一副,相加==相减,结果为符号
// 正正或者负负,符号不变,
if(!a.positive == b.positive){
res.divChild = a.divChild*b.divMum - b.divChild*a.divMum;
res.positive = res.divChild < 0 ? !a.positive:a.positive; // 正+负-》得负,符号为负,负+正-》得负,符号为正
if(res.divChild < 0) res.divChild = -res.divChild;
if(res.divChild == 0) res.positive = true;
}else{
res.positive = a.positive;
res.divChild = a.divChild*b.divMum + b.divChild*a.divMum;
}
res.divMum = a.divMum * b.divMum;

return res;
}

void reversePositive(){positive = !positive;}

friend DivNum operator -(DivNum const &a, DivNum const &b){
// a-b = a + (-b)
DivNum c = b;
c.reversePositive();
return a + c;

}

friend DivNum operator *(const DivNum &a,const DivNum &b){
DivNum res;

res.positive = (a.positive && b.positive)||(!a.positive && !b.positive); // 正正得正,负负得正
res.divChild = a.divChild * b.divChild;
res.divMum = a.divMum * b.divMum;

if(res.divChild == 0) res.positive = true;

return res;

}
friend DivNum operator /(const DivNum &a, const DivNum &b){
DivNum res;

res.positive = (a.positive && b.positive)||(!a.positive && !b.positive); // 正正得正,负负得正
res.divChild = a.divChild * b.divMum;
res.divMum = a.divMum * b.divChild;

if(res.divChild == 0) res.positive = true;

return res;
}

void out(){

if(!isSimple){
simplify();
isSimple =true;
}

if(divMum){ // 分母不为0
if(!positive) cout << "(-";
if(extInt) cout << integer;
if(extInt && extDiv) cout << " ";
if(extDiv) cout << divChild << "/" << divMum;
if(!positive) cout << ")";
}else{
cout << "Inf";
}

}

};
int main(){

// 得到两个数字
char str1[30],str2[30];
scanf("%s%s",str1,str2);

DivNum a,b;
a.in(str1);
b.in(str2);

DivNum res[4];
char op[4]={'+','-','*','/'};

res[0] = a+b;
res[1] = a-b;
res[2] = a*b;
res[3] = a/b;

for (int i = 0; i < 4; ++i) {
a.out();cout << " " << op[i] << " ";b.out();cout << " = ";res[i].out();cout << endl;
}
// 化为最简分数保存起来

// 进行四则运算得到四个结果

// 输出

return 0;
}

过程资料

点评:

这道题目比较繁琐,涉及的点比较多,坑点也多,写起来比较蛋疼。

测试点:

第3、4个测试点用的是较大数字,如果仅仅用 int 整数的, 可能会导致预料外的错误,例如第4个测试点出现了浮点错误。解决方法是改为 long long。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: