zoukankan      html  css  js  c++  java
  • PAT 1034 有理数四则运算(20)

    题目

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

    过程资料

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


    测试点:

    1. 第3、4个测试点用的是较大数字,如果仅仅用 int 整数的, 可能会导致预料外的错误,例如第4个测试点出现了浮点错误。解决方法是改为 long long。
  • 相关阅读:
    xpath语法速查
    负载均衡设计
    Nginx负载均衡配置实例详解
    实现基于DNS的负载均衡
    建立双线服务器(双线游戏服务器)
    python学习
    python多线程概念
    python 多线程就这么简单(续)
    打包一沓开源的 C/C++ 包管理工具送给你!
    讲解开源项目:功能强大的 JS 文件上传库
  • 原文地址:https://www.cnblogs.com/tangyikejun/p/4300408.html
Copyright © 2011-2022 走看看