PAT B1034 有理数四则运算 (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、split()函数:将分数读入string变量中,将其分为分子和分母储存在long long变量中;

          2、基于split(),再分别写四个加减乘除函数;

         3、together_simple(), 输入分子分母部分,将其化为最简形式,并储存在string中。

难点:3中如何化为最简真分数。

          a、从1循环至分子,分母的小者,找到其最大的公因子。复杂度较大。

          b、辗转相除法。

注意:测试点3错误:用 int 存储加减乘除时可能存在数值越界,应该采用 long long

 

#include<iostream>
#include<string>

using namespace std;

void split(const string& a, long long& a1, long long& a2);
int largest_factor(int a, int b);
string& together_simple(string& ans, long long c1, long long c2);
string& add(string& ans, long long a1, long long a2, long long b1, long long b2);
string& subtract(string& ans, long long a1, long long a2, long long b1, long long b2);
string& mutiple(string& ans, long long a1, long long a2, long long b1, long long b2);
string& divided(string& ans, long long a1, long long a2, long long b1, long long b2);

void split(const string& a, long long& a1, long long& a2) //把分数拆分为分子和分母
{
    long long i = 0; long long flag = 0;
    if(a[0]=='-')
    {
        i++;
        flag = 1;
    }
    a1 = a2 = 0;
    while(a[i]!='/')
        a1 = a1*10 + (a[i++]-'0');
    i++;
    while(a[i]!='\0')
        a2 = a2*10 + (a[i++]-'0');
    if(flag==1)
        a1 = -a1;
}

int largest_factor(int a, int b)    //辗转相除法求最大公因子
{
    if(a==0 || b==0)
        return 0;
    int big, small;
    if(a>b)
    {
        big = a;
        small = b;
    }
    else
    {
        big = b;
        small = a;
    }
    int bigyin, yu;
    while(1)
    {
        if(big%small==0)
        {
            bigyin = small;
            break;
        }
        else
        {
            yu = big%small;
            big = small;
            small = yu;
        }
    }
    return bigyin;
}

string& together_simple(string& ans, long long c1, long long c2)   //把分子分母化作最简形式储存在string中
{
    long long flag = 0;
    if(c1<0)
    {
        flag = 1;
        c1 = -c1;
    }
    long long zheng, fen;
    zheng = c1/c2; fen = c1%c2;
    if(fen!=0)
    {
        int bigyin;
        bigyin = largest_factor(fen, c2);
        fen = fen/bigyin; c2 = c2/bigyin;
    }
/*    for(long long i=2; i<=fen && i<=c2; i++)  //时间复杂度大,将分数部分化为最简;注意:i 从1开始, 而不能从0开始
    {
        if(fen%i==0 && c2%i==0)
        {
            fen = fen/i; c2 = c2/i; i=1;  // i=1必须要有,否则化简不彻底,例如4/12 -> 2/6;
        }
    }*/

    if(flag==1)                     //将符号,整数部分,分数部分拼接到string ans 中;注意括号和空格所加位置的逻辑
        ans += "(-";
    if(fen==0)
        ans += to_string(zheng);
    else if(fen!=0 && zheng!=0)
    {
        ans += to_string(zheng);
        ans += " ";
    }
    if(fen!=0)
    {
        ans += to_string(fen);
        ans += "/";
        ans += to_string(c2);
    }
    if(flag==1)
        ans += ")";
    return ans;
}

string& add(string& ans, long long a1, long long a2, long long b1, long long b2)
{
    ans = "";
    a1=a1*b2; b1=a2*b1;
    a2=a2*b2; b2=a2;
    long long c1, c2;
    c1=a1+b1; c2=a2;
    together_simple(ans, c1, c2);
    return ans;
}

string& subtract(string& ans, long long a1, long long a2, long long b1, long long b2)
{
    ans = "";
    b1 = -b1;
    return add(ans, a1, a2, b1, b2);
}

string& mutiple(string& ans, long long a1, long long a2, long long b1, long long b2)
{
    ans = "";
    long long c1, c2;
    c1 = a1*b1;
    c2 = a2*b2;
    return together_simple(ans, c1, c2);
}

string& divided(string& ans, long long a1, long long a2, long long b1, long long b2)
{
    ans = "";
    if(b1==0)
    {
        ans += "Inf";
        return ans;
    }
    if(b1<0)
    {
        b1 = -b1;
        b2 = -b2;
    }
    return mutiple(ans, a1, a2, b2, b1);
}


int main()
{
    string a, b;
    cin >> a >> b;
    long long a1, a2, b1, b2;
    split(a, a1, a2);
    split(b, b1, b2);
    string a_simple, b_simple;
    together_simple(a_simple, a1, a2);
    together_simple(b_simple, b1, b2);
    string ans;
    cout << a_simple << " + " << b_simple << " = " << add(ans, a1, a2, b1, b2) << endl;
    cout << a_simple << " - " << b_simple << " = " << subtract(ans, a1, a2, b1, b2) << endl;
    cout << a_simple << " * " << b_simple << " = " << mutiple(ans, a1, a2, b1, b2) << endl;
    cout << a_simple << " / " << b_simple << " = " << divided(ans, a1, a2, b1, b2) << endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值