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

写了很久,主要是要把不同的情况都考虑进去,另外很坑的是题目虽然说保证正确的输出中没有超过整型范围的整数,但是用int出现错误,

网上一查才了解在计算过程中2个int型相乘会超出范围,就干脆全部用long long了

#include <stdio.h>
#include <math.h>

typedef long long ll;
ll gcd(ll a,ll b);
ll output(ll a1,ll b1);
ll judge(ll *a,ll *b,ll *flag);
int main()
{
    char a[4] = "+-*/";
    ll a1,b1,a2,b2;
    ll i;
    ll dem,quo1,quo2;
    ll b[4];
    scanf("%lld/%lld %lld/%lld",&a1,&b1,&a2,&b2);
    dem = b1*b2;//和差积的分母
    b[0] = a1*b2 + a2*b1;//和的分子
    b[1] = a1*b2 - a2*b1;//差的分子
    b[2] = a1*a2;//积的分子
    if(a2!=0)
    {
        quo1 = a1*b2;//商的分子
        quo2 = a2*b1;//商的分母
        if(quo2<0)
        {
            quo2 *= -1;
            quo1 *= -1;
        }
    }
    for(i=0;i<4;i++)
    {
        output(a1,b1);
        printf(" %c ",a[i]);
        output(a2,b2);
        printf(" = ");
        i==3 ? (a2==0 ? printf("Inf") : output(quo1,quo2)): output(b[i],dem);//除法特殊情况
        printf("\n");
    }
    return 0;
}

ll gcd(ll a,ll b)
{
    ll temp;
    if(a<b)
    {
        temp = a;
        a = b;
        b = temp;
    }
    return b==0 ? a : gcd(b,a%b);
}

ll output(ll a1,ll b1)
{
    ll flag = 0;
    ll minusflag;
    minusflag = judge(&a1,&b1,&flag);
    if(b1==1)//分母为1时
    {
        printf("%s%lld%s",minusflag==1 ? "(-" : "",a1,minusflag==1 ? ")" : "");
    }
    else{
        if(flag==0)//分子不大于分母时
        {
            printf("%s%lld/%lld%s",minusflag==1 ? "(-" : "",a1,b1,minusflag==1 ? ")" : "");
        }
        else{//分子大于分母时
            printf("%s%lld %lld/%lld%s",minusflag==1 ? "(-" : "",flag,a1,b1,minusflag==1 ? ")" : "");
        }
    }
    return 0;
}

ll judge(ll *a,ll *b,ll *flag)
{
    ll minusflag = 0;
    ll gcd1;
    if(*a<0)//分子小于0时为负数,标记
    {
        minusflag = 1;
        *a = fabs(*a);//求最大公约数时需均为正整数
    }
    if((gcd1 = gcd(*a,*b))!=1)
    {
        *a = *a / gcd1;
        *b = *b / gcd1;//消去公约数注意两个不能都用a = a/gcd(a,b)这种形式因为在第一条执行后a的值已经变了,这样得出的b会错误,一开始这么写了。。
    }
    if(*a>*b && *b!=1)
    {
        *flag = *a / *b;
        *a %= *b;  //分子大于分母时最简形式
    }
    return minusflag;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值