PTA甲级 1088 Rational Arithmetic (20分)


强烈推荐,刷PTA的朋友都认识一下柳神–PTA解法大佬

本文由参考于柳神博客写成

柳神的CSDN博客,这个可以搜索文章

柳神的个人博客,这个没有广告,但是不能搜索

PS

题目原文

For two rational numbers, your task is to implement the basic arithmetics, that is, to calculate their sum, difference, product and quotient.

Input Specification:

Each input file contains one test case, which gives in one line the two rational numbers in the format a1/b1 a2/b2. The numerators and the denominators are all in the range of long int. If there is a negative sign, it must appear only in front of the numerator. The denominators are guaranteed to be non-zero numbers.

Output Specification:

For each test case, print in 4 lines the sum, difference, product and quotient of the two rational numbers, respectively. The format of each line is number1 operator number2 = result. Notice that all the rational numbers must be in their simplest form k a/b, where k is the integer part, and a/b is the simplest fraction part. If the number is negative, it must be included in a pair of parentheses. If the denominator in the division is zero, output Inf as the result. It is guaranteed that all the output integers are in the range of long int.

Sample Input 1:

2/3 -4/2

Sample Output 1:

2/3 + (-2) = (-1 1/3)
2/3 - (-2) = 2 2/3
2/3 * (-2) = (-1 1/3)
2/3 / (-2) = (-1/3)

Sample Input 2:

5/3 0/6

Sample Output 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

生词如下:

arithmetics 算术 product 乘积 quotient 商

题目大意:

① 输出的格式符号必须在前面. 5/3 的话要写成 1 2/3这样的形式.

② 还有就是注意这个格式是long int ,注意自己的占位符,判断符号的时候,不可以使用相乘的方法,有可能会溢出.

我的思路:

①:计算之前要先化简.用最小的公约数.来相除.然后化简.

②:计算完了之后,也要化简.这点非常的重要.

③:然后就是自己写代码的时候,要注意细节.细节非常的重要.(老是在一些简单的地方出错,真的非常搞.)

④:就是非常严重的,我的思路太乱了,写的是什么东西.

代码如下:

#include<iostream>
using namespace std;
//这个就是求最大公约数的函数
long int gcd(long int a, long int b) {
	if (a == 0)
		return 1;
	return b == 0 ? abs(a) : gcd(b, a % b); 
}
//输出一个分数的函数
void Print_grade(long int a,long int b) {
	long int gcd1 = gcd(a, b);
	a = a / gcd1;
	b = b / gcd1;
	//如果a1是负数的话
	if (a < 0) {
		//而且还是整数的话
		if (b == 1) {
			printf("(%ld)", a);
		}
		//不是负整数,但是有多余的数字的话,就比如5/3这样的情况.
		else if (-a > b) {
			printf("(-%ld %ld/%ld)", -a / b, -a % b, b);
		}
		//就是最一般的负整数.
		else {
			printf("(%d/%d)", a, b);
		}
	}
	//a是正数的话
	else if(a>0){
		//而且还是整数的话
		if (b == 1) {
			printf("%ld", a);
		}
		//不是负整数,但是有多余的数字的话,就比如5/3这样的情况.
		else if (a > b) {
			printf("%ld %ld/%ld", a / b, a % b, b);
		}
		//就是最一般的负整数.
		else {
			printf("%d/%d", a, b);
		}
	}
	else if (a == 0) {
		printf("0");
	}
}
//输出前面整个不等式
void Print_Formula(long int a1, long int b1, long int a2, long int b2,char c) {
	Print_grade(a1, b1);
	printf(" %c ", c);
	Print_grade(a2, b2);
	cout << " = ";
}
//计算加法,并且输出
void Print_Add(long int a1, long int b1, long int a2,long int b2) {
	long int Divisor = gcd(b1, b2);
	if (a1 != 0 && a2 != 0) {
		//这个就是最小的公倍数
		long int Time = b1 * b2 / Divisor;
		a1 = Time / b1 * a1;
		a2 = Time / b2 * a2;
		a1 = a1 + a2;
		Print_grade(a1, Time);
	}
	else if (a1 == 0) {
		Print_grade(a2, b2);
	}
	else {
		Print_grade(a1, b1);
	}
	cout << "\n";
}
//计算剑法,并且输出
void Print_Decline(long int a1, long int b1, long int a2, long int b2) {
	long int Divisor = gcd(b1, b2);
	if (a1 != 0 && a2 != 0) {
		//这个就是最小的公倍数
		long int Time = b1 * b2 / Divisor;
		a1 = Time / b1 * a1;
		a2 = Time / b2 * a2;
		a1 = a1 - a2;
		Print_grade(a1, Time);
	}
	else if (a1 == 0) {
		Print_grade(a2, b2);
	}
	else {
		Print_grade(a1, b1);
	}
	cout << "\n";
}
//计算乘法,并且输出
void Print_Product(long int a1, long int b1, long int a2, long int b2) {
	long int gcd1=0, gcd2=0;
	if (a1 != 0 && a2 != 0) {
		gcd1 = gcd(a1, b2);
		a1 = a1 / gcd1;
		b2 = b2 / gcd1;
		gcd2 = gcd(a2, b1);
		a2 = a2 / gcd2;
		b1 = b1 / gcd2;
		a1 = a1 * a2;
		b1 = b1 * b2;
		Print_grade(a1, b1);
	}
	else {
		printf("0");
	}
}
//计算除法,并且输出

int main(void) {
	string a, b;
	long int  a1, b1, a2, b2;
	scanf("%ld/%ld %ld/%ld", &a1, &b1, &a2, &b2);
	//改变一下符号,因为我下面的代码都是默认符号在分母上的,
	//但是测试的数据有点符号是在分子上的.
	if (a1 < 0 && b1 < 0) {
		a1 = -a1;
		b1 = -b1;
	}
	else if (a1 > 0 && b1 < 0) {
		a1 = -a1;
		b1 = -b1;
	}
	if (a2 < 0 && b2 < 0) {
		a2 = -a2;
		b2 = -b2;
	}
	else if (a2 > 0 && b2 < 0) {
		a2 = -a2;
		b2 = -b2;
	}
	
	char sybmol[4] = { '+','-','*','/' };
	long int Divisor=gcd(a1,b1);					//公约数
	a1 = a1 /Divisor;
	b1 = b1 / Divisor;

	Divisor = gcd(a2, b2);
	a2 = a2 / Divisor;
	b2 = b2 / Divisor;
	Print_Formula(a1, b1, a2, b2, sybmol[0]);
	Print_Add(a1, b1, a2, b2);
	Print_Formula(a1, b1, a2, b2, sybmol[1]);
	Print_Decline(a1, b1, a2, b2);
	Print_Formula(a1, b1, a2, b2, sybmol[2]);
	Print_Product(a1, b1, a2, b2);
	cout << "\n";
	Print_Formula(a1, b1, a2, b2, sybmol[3]);

	if (a2 == 0) {
		printf("Inf");
	}
	else if (a1 == 0) {
		printf("0");
	}
	else  {
		if (a2 < 0) {
			long int t = -a2;
			a2 = -b2;
			b2 = t;
			Print_Product(a1, b1, a2, b2);
		}
		else {
			long int t = a2;
			a2 = b2;
			b2 = t;
			Print_Product(a1, b1, a2, b2);
		}
	}
	return 0;
}

然后让我们看一看柳神的代码.洗一下眼睛.

#include <iostream>
#include <cmath>
using namespace std;
long long a, b, c, d;
//柳神经常用的求公约数的算法.一个简单的递归算法
long long gcd(long long t1, long long t2) {
    return t2 == 0 ? t1 : gcd(t2, t1 % t2);
}
//核心代码.化简分数
void func(long long m, long long n) {
    //然后来判断m和n里面有没有0
    //m分子为0,那么结果就是0
    //n分母为0,那么结果就是Inf
    if (m * n == 0) {
        printf("%s", n == 0 ? "Inf" : "0");
        return;
    }
    //flag用来表示,是不是异号
    bool flag = ((m < 0 && n > 0) || (m > 0 && n < 0));
    m = abs(m); n = abs(n);
    //不管用不用得到,先算了再说.
    long long x = m / n;
    //非常巧妙的写法,用一个三目运算符代替了if语句,这样简化的语句.
    printf("%s", flag ? "(-" : "");
    //我怎么就没有想到呢,就用了一堆的if else 语句.柳神这样就非常的清楚.
    if (x != 0) printf("%lld", x);
    if (m % n == 0) {   //在判断是不是整数.如果是整数的话,那就直接输出一个)就OK了.
        if (flag) printf(")");
        return;
    }
    //这个是那个数字后面的空格.
    if (x != 0) printf(" ");
    m = m - x * n;
    long long t = gcd(m, n);
    m = m / t; n = n / t;
    //又是巧妙的操作.
    printf("%lld/%lld%s", m, n, flag ? ")" : "");
}
int main() {
    scanf("%lld/%lld %lld/%lld", &a, &b, &c, &d);
    //后面因为大佬化简的算法写的好的原因,只要无脑带一带就OK了.
    func(a, b); printf(" + "); func(c, d); printf(" = "); func(a * d + b * c, b * d); printf("\n");
    func(a, b); printf(" - "); func(c, d); printf(" = "); func(a * d - b * c, b * d); printf("\n");
    func(a, b); printf(" * "); func(c, d); printf(" = "); func(a * c, b * d); printf("\n");
    func(a, b); printf(" / "); func(c, d); printf(" = "); func(a * d, b * c);
    return 0;
}

如果这篇文章对你有张帮助的话,可以用你高贵的小手给我点一个免费的赞吗

相信我,你也能变成光.

在这里插入图片描述

如果你有任何建议,或者是发现了我的错误,欢迎评论留言指出.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值