PAT乙级(Basic Level)练习题 分数运算

题目描述
计算机中采用浮点数表示所有实数,但这意味着精度丢失。例如无法精确表示“1/3”。
NowCoder最近要处理很多金融问题,这些账目不允许出现精度丢失,因为差之毫厘谬之千里。你能帮他实现一套分数的计算器吗?

输入描述:
输入包含多组数据。
每组数据一行,包含两个分数和一个运算符,中间用空格隔开。
其中分子与分母均为不大于30的正整数。

输出描述:
对应每一组数据,输出两个分数的计算结果。
要求输出最简分数,即分子与分母互质。

输入例子:

1/3 2/3 +
1/5 1/4 -
1/2 1/3 *
2/3 4/3 /

输出例子:

1/1
-1/20
1/6
1/2

\color{blue}解题思路:
本题的关键是最大公因数最小公倍数的求解。

两数的最大公因数求解常用辗转相除法,比如a,b两数(假设a >= b)

while (a % b != 0) {
	b’ 赋值为 a / b 余数 (即 a % b)
	a‘ 赋值为 b
	
	a = a’, b = b'
}

两数的最小公倍数求解有个数学规律

a、b最小公倍数 = a * b / (a、b最大公因数)

\color{blue}代码实现:

#include <iostream>
#include <math.h>
using namespace std;

// 求number1、number2的最大公因数
int gcd(int number1, int number2) {
    int tempNum = 0;
    //保持number1不小于number2
    if (number1 < number2) {
        //借助tempNum,将number1、number2进行交换
        tempNum = number1;
        number1 = number2;
        number2 = tempNum;
    }
    //判断number1是否能整除number2
    while (number1 % number2 != 0) {
        //ba余数赋给tempNum
        tempNum = number1 % number2;
        //把number2赋给number1,tempNum赋给number2
        //由于进行求余时,number2是除数,tempNum是余数,所以number2 > tempNum
        //赋值操作后继续维持了 number1 > number2
        number1 = number2;
        number2 = tempNum;
    }
    return number2;
}

// 求number1、number2的最小公倍数
int lcm(int number1, int number2) {
    //最小公倍数 = 两数相乘 / 最大公因数
    return number1 * number2 / gcd(number1, number2);
}


int main(int argc, const char * argv[]) {
    char op = '\0';
    // 分数numerator1/denominator1,参数1   分数numerator2/denominator2  参数2
    int numerator1 = 1, denominator1 = 1, numerator2 = 1, denominator2 = 1;
    //scanf返回值为正确输入数据的变量个数,当一个变量都没有成功获取数据时,此时返回-1
    while (scanf("%d/%d %d/%d %c", &numerator1, &denominator1, &numerator2, &denominator2, &op) != - 1) {
        //记录结果是否为负数
        bool flag = false;
        //分数numerator3/denominator3,结果
        int numerator3 = 0, denominator3 = 0;
        if (op == '+') {
            //处理分数加法,先分母同分,然后分子与分母交叉相乘
            denominator3 = denominator1 * denominator2;
            numerator3 = numerator1 * denominator2 + numerator2 * denominator1;
        }
        if (op == '-') {
            //处理分数减法,先分母同分,然后分子与分母交叉相乘
            denominator3 = denominator1 * denominator2;
            numerator3 = numerator1 * denominator2 - numerator2 * denominator1;
            if (numerator3 < 0) {
            	//这里单独记录负号,是因为求解公因数、公倍数是不能有负数
                flag = true;
                numerator3 = -numerator3;
            }
        }
        if (op == '*') {
            //处理分数乘法,分母相乘,分子相乘
            denominator3 = denominator1 * denominator2;
            numerator3 = numerator1 * numerator2;
        }
        if (op == '/') {
            //处理分数除法,分母1 分子2 相乘作分母,分子1 分母2 相乘 作分子
            denominator3 = denominator1 * numerator2;
            numerator3 = numerator1 * denominator2;
        }
        if (numerator3 == 0) {
            printf("0\n");
        } else {
            //分子、分母分别除最大公因数进行约分
            int tempNum = gcd(numerator3, denominator3);
            numerator3 /= tempNum;
            denominator3 /= tempNum;
            //如果是减法可能产生负数,因此需要输出负号
            printf((flag ? "-%d/%d\n" : "%d/%d\n"), numerator3, denominator3);
        }
    }
    return 0;
}

在这里插入图片描述

发布了1005 篇原创文章 · 获赞 269 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/104649018
今日推荐