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 = 01 2/3 / 0 = Inf
迄今为止,写了三个小时还没写出来的题,已经完全被搞晕掉了,我要歇一歇,改天清醒了再来!
这题前两天把我搞晕了,今天总算是整明白了~以后要训练自己养成写思路的习惯。看到题后,先在草稿纸上写下自己的思路,或者是伪代码。然后再开始敲代码!否则脑子越来越晕,越整越浆糊!不要想想就开始敲代码,感觉会给面试官留下不好的印象。废话不说了,说说这题的思路。
这题的题意不复杂,有理数的运算。我认为关键点有以下几点:
1、构建一个结构体Num,存放有理数。结构体中成员变量包括:符号,整数部分,分子,分母;
2、将输入字符串对应成Num中的格式。并判断第二个数是否为0的情况。为0情况特殊处理;
3、不为零的数,对两数进行加减乘除的运算。注意,输出的数格式都为假分数,此时直接用假分数进行计算,最后再化简即可。
4、对计算的结果,化成标准的最简真分数。这里涉及同时约分。(求最大公约数,再约分即可)
以下是我最后写出来的代码(代码还不是很优美,但是功能是可以的)
#include<vector> #include <sstream> #include<cmath> #include<iomanip> #include<iostream> #include <ctype.h> #include <stdlib.h> using namespace std; //1034. 有理数四则运算(20) struct RatNum//创建一个结构体,表示一个有理数 { bool sign;//1表示为正数,0表示为负数 long int intpart; long int childp; long int prtp; }; //一系列要用到的函数申明,在实现部分写具体的功能 int maxCommon(int a, int b); RatNum StringToRatNum(string s); RatNum ToStdForm(RatNum num); void Outputform(RatNum num); RatNum StringToRatNum(string s)//注意输入的时候,本来就是一个假分数,因此这里将整数部分赋值为0 { RatNum ratnum; int fh = s.find('/');//找到分号的位置 ratnum.intpart = 0; string childs; string prts; if (s[0] == '-')//为负数的情况 { ratnum.sign = 0; childs = s.substr(1, fh); prts = s.substr(fh + 1, s.length() - 1); } else//为正数的情况 { ratnum.sign = 1; childs = s.substr(0, fh); } prts = s.substr(fh + 1, s.length() - 1); ratnum.childp = atoi(childs.c_str()); ratnum.prtp = atoi(prts.c_str()); return ratnum; } // 顺便借题学习求最大公约数和最小公倍数的方法 int maxCommon(int a, int b)//求最大公约数 { if (b == 0) return a; else return maxCommon(b, a%b); } RatNum ToStdForm(RatNum num)//将假分数化为最简形式 { RatNum ratnum; ratnum.sign = num.sign; int child = 0; int part = 0; ratnum.intpart = num.childp / num.prtp; child = num.childp % num.prtp; part = num.prtp; int temp = maxCommon(child, part); ratnum.childp = child / temp; ratnum.prtp = part / temp; return ratnum; } void Outputform(RatNum num)//函数实现标准格式的输出,包括:1、负数加括号;2、分子为0的情况;3、整数部分为0的情况 { if (num.sign == false)//如果是负数,要加括号 { if (num.childp == 0) { cout << "(-" << num.intpart << ")"; } else { if (num.intpart == 0) { cout << "(-" << num.childp << "/" << num.prtp << ")"; } else { cout << "(-" << num.intpart << " " << num.childp << "/" << num.prtp << ")"; } } } else//为正数的情况 { if (num.childp == 0) { cout << num.intpart; } else { if (num.intpart == 0) { cout << num.childp << "/" << num.prtp; } else { cout << num.intpart << " " << num.childp << "/" << num.prtp; } } } } int main() { string a, b; cin >> a >> b; RatNum numa = StringToRatNum(a);//将输入的两个字符串表示为有理数的形式 RatNum numb = StringToRatNum(b); RatNum he1, cha1, ji1, shang1; he1.intpart = 0;//计算时均用假分数进行计算,因此 cha1.intpart = 0; ji1.intpart = 0; shang1.intpart = 0; RatNum opt_numa = ToStdForm(numa);//将假分数转化成题目要求的形式,真分数,且最简形式 RatNum opt_numb = ToStdForm(numb); if (numb.childp != 0) { //以下均先用假分数进行计算 if (numa.sign == numb.sign)//两数同号 { ji1.sign = true; shang1.sign = true; if (numa.sign == true)//两数同为正 { //和 he1.sign = true; //差 cha1.childp = numa.childp*numb.prtp - numb.childp*numa.prtp;//计算差值 if (cha1.childp >= 0) { cha1.sign = true; } else { cha1.sign = false; cha1.childp = abs(cha1.childp);//这里要注意取绝对值,数的正负在符号位反应,其他的正数,分子,分母部分均设为正数 } } else//两个数同时为负数 { he1.sign = false; cha1.childp = numb.childp*numa.prtp - numa.childp*numb.prtp; if (cha1.childp >= 0) { cha1.sign = true; } else { cha1.sign = false; cha1.childp = abs(cha1.childp); } } //和 he1.childp = numa.childp*numb.prtp + numa.prtp*numb.childp; } else//两数异号 { ji1.sign = false; shang1.sign = false; if (numa.sign == true)//a正b负 { //和 he1.childp = numa.childp*numb.prtp - numa.prtp*numb.childp; if (he1.childp >= 0) { he1.sign = true; } else { he1.sign = false; he1.childp = abs(he1.childp); } //差 cha1.sign = true; cha1.childp = numa.childp*numb.prtp + numb.childp*numa.prtp; } if (numa.sign == false)//a负b正 { //和 he1.childp = numb.childp*numa.prtp - numa.childp*numb.prtp; if (he1.childp >= 0) { he1.sign = true; } else { he1.sign = false; he1.childp = abs(he1.childp); } //差 cha1.sign = false; cha1.childp = numa.childp*numb.prtp + numa.prtp*numb.childp; } } //和 he1.prtp = numa.prtp*numb.prtp; //差 cha1.prtp = numa.prtp*numb.prtp; //积 ji1.childp = numa.childp*numb.childp; ji1.prtp = numa.prtp*numb.prtp; //商 shang1.childp = numa.childp*numb.prtp; shang1.prtp = numa.prtp*numb.childp; RatNum he = ToStdForm(he1);//将假分数转化为标准形式 RatNum cha = ToStdForm(cha1); RatNum ji = ToStdForm(ji1); RatNum shang = ToStdForm(shang1); Outputform(opt_numa); cout << " + "; Outputform(opt_numb); cout << " = "; Outputform(he); cout << endl; Outputform(opt_numa); cout << " - "; Outputform(opt_numb); cout << " = "; Outputform(cha); cout << endl; Outputform(opt_numa); cout << " * "; Outputform(opt_numb); cout << " = "; Outputform(ji); cout << endl; Outputform(opt_numa); cout << " / "; Outputform(opt_numb); cout << " = "; Outputform(shang); cout << endl; } else//特殊处理第二个数为0的情况 { Outputform(opt_numa); cout << " + "; Outputform(opt_numb); cout << " = "; Outputform(opt_numa); cout << endl; Outputform(opt_numa); cout << " - "; Outputform(opt_numb); cout << " = "; Outputform(opt_numa); cout << endl; Outputform(opt_numa); cout << " * "; Outputform(opt_numb); cout << " = 0"; cout << endl; Outputform(opt_numa); cout << " / "; Outputform(opt_numb); cout << " = Inf"; cout << endl; } return 0; }