写在最前:欢迎批评,欢迎任意地方的指正,用你们的优秀的java代码砸死我吧!!
问题——————
本题要求编写程序,计算 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
解题思路:
题不是难题,但是麻烦,最讨厌的就是麻烦的简单题。。敲半天要注意的细节特别多,还没有什么成就感,这题主要就是在化简上可能有格式错误,四则运算的实现都特别简单,所以单独把化简拿出来认真写,只要把值存对,化简写对,剩下的就只是计算的问题了,再也不用考虑别的格式问题。化简方面主要就是注意正反,注意真分数假分数,注意是整数的情况,注意是0的情况就可以了。最后就是一个坑,题中是说给出的数据不超过int类型,但是他没有说相乘的结果不会超出int,所以直接使用long类型来写,如果用int会使得两个错误点错误。
package not.die.in.here;
import java.io.*;
//满分
//他只是说保证所有给出是int,但是可能乘法乘出来超过int的类型
//直接用long
public class _1034_RationalCal {
//静态内部类
static class Rational{
long up,down;//分子分母
boolean sign;//符号,true代表+,false代表-
String format;//最后的格式化的字符串存储
public Rational() {}//无参构造器
public Rational(String a) {//构造器,为了方便直接使用从外界读入的String格式
if(a.indexOf('-')==0) {//如果第一个字符是-的话就是负数
sign=false;//负数
String[] buf = a.split("/");
up = -Long.parseLong(buf[0]);//分别保存分子和分母
down = Long.parseLong(buf[1]);
simple();//调用化简函数
}else {
sign=true;//正数
String[] buf = a.split("/");
up = Long.parseLong(buf[0]);//分别处理
down = Long.parseLong(buf[1]);
simple();//调用化简
}
}
public void simple() {
if(up==0) {//首先,如果分子是0,那么值肯定是0
format = "0";
return;
}else {
long num = GCD(up,down);//最大公约数
up = up/num;
down = down/num;//最简
if(up<down) {//真分数
format = up+"/"+down;//直接分数形式
return;
}else {//假分数
if(down == 1) {
format=up+"";//如果是最简形式并且分母为1,那么直接输出分子
return;
}else {
long x = up/down;//假分数变带分数
long tempUp = up-down*x;
format = x+" "+tempUp+"/"+down;
return;
}
}
}
}
@Override
public String toString() {//把化简的值经过符号处理输出,后面使用的时候可以直接输出对象
if(format.equals("0"))
return format;
if(sign)
return format;
else
return "(-"+format+")";
}
}
//欧几里得算法 递推法(效率最高)
/*private static long GCD(long a,long b){
return (a==0?b:GCD(b%a,a));
}*/
public static Rational add(Rational a,Rational b) {//加法
Rational c = new Rational();
if(!a.sign^b.sign) {//同正同负
//同号情况下,值累加,符号不变
c.down = a.down*b.down;
c.up = a.up*b.down+b.up*a.down;
c.sign=a.sign;
c.simple();
return c;
}else {
//异号情况下,值做差,取绝对值较大的符号
c.down = a.down*b.down;
c.up = Math.abs(a.up*b.down-b.up*a.down);
if(a.up/a.down>=b.up/b.down)
c.sign = a.sign;
if(b.up/b.down>=a.up/a.down)
c.sign = b.sign;
c.simple();
return c;
}
}
public static Rational minus(Rational a,Rational b) {
Rational c = new Rational();//相减的情况可以充分利用写好的代码,吧后面的数的符号相反,调用加法
c.up = b.up;
c.down = b.down;
c.sign = !b.sign;
return add(a,c);
}
public static Rational mulity(Rational a,Rational b) {
//乘法,分子分母分别相乘,同号取正,异号取负
Rational c = new Rational();
c.up = a.up*b.up;
c.down = a.down*b.down;
c.sign = !a.sign^b.sign;
c.simple();
return c;
}
public static String devide(Rational a,Rational b) {
//触发单独把返回值变成String,因为有INF的可能性
if(b.toString().equals("0")) {
return "Inf";//分母0则返回inf
}else {//如果分母不是0,那就把b的分子分母调换,调用乘法,最后输出对象的toString
Rational c = new Rational();
c.up = b.down;
c.down = b.up;
c.sign = b.sign;
return mulity(a,c).toString();
}
}
public static long GCD(long a,long b) {
while(b > 0) {//欧几里得
long num = a%b;
a=b;
b=num;
}
return a;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String buf[] = bf.readLine().split("\\s+");//任意个空格分割
Rational a = new Rational(buf[0]);
Rational b = new Rational(buf[1]);
//格式化直接输出
System.out.println(a+" + "+b+" = "+ add(a, b));
System.out.println(a+" - "+b+" = "+minus(a, b));
System.out.println(a+" * "+b+" = "+mulity(a, b));
System.out.println(a+" / "+b+" = "+devide(a, b));
}
}