PAT [B1034 有理数四则运算] C语言AC

该博客介绍了一个C++程序,用于计算两个有理数的加、减、乘、除,并确保结果是最简形式。程序通过辗转相除法计算最大公约数以简化分数,同时处理分母为零的情况。代码包含详细注释,解释了递归求最大公约数的逻辑和输出有理数的规则。

本题要求编写程序,计算 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

思路:

参考了柳神的思路,统一用一个函数来化简分子和分母并输出结果,四则运算的计算过程在主函数中完成并将结果的分子分母作为参数传入化简函数。化简函数的具体思路见代码注释↓

化简需要求分子和分母的最大公约数,可以通过递归的形式来写辗转相除法。原理是,假设a>=b,则b和a%b(a除b的余数)的最大公约数也是a和b的最大公约数,那么b和a%b作为下一次递归的参数就减小了问题的规模。假如a<b,则b和a%b作为下一次递归的参数就是交换了位置,转化为a>b的情况。递归结束的边界是b==0。

所有变量必须用long存放否则不够大。

#include<stdio.h>
long gcd(long a,long b);
void simprint(long up,long down);
int main(void){
    long a1,b1,a2,b2;
    scanf("%ld/%ld%ld/%ld",&a1,&b1,&a2,&b2);
    
    simprint(a1,b1);
    printf(" + ");
    simprint(a2,b2);
    printf(" = ");
    simprint(a1*b2+a2*b1,b1*b2);
    printf("\n");
    
    simprint(a1,b1);
    printf(" - ");
    simprint(a2,b2);
    printf(" = ");
    simprint(a1*b2-a2*b1,b1*b2);
    printf("\n");
    
    simprint(a1,b1);
    printf(" * ");
    simprint(a2,b2);
    printf(" = ");
    simprint(a1*a2,b1*b2);
    printf("\n");
    
    simprint(a1,b1);
    printf(" / ");
    simprint(a2,b2);
    printf(" = ");
    simprint(a1*b2,b1*a2);
    printf("\n");
    
    return 0;
}
void simprint(long up,long down){
    int flag=0;//表示正负
    if(down==0){//分母为0是不合法的
        printf("Inf");
        return;
    }else if(down<0){//分母<0则将分子分母正负交换
        up=-up;
        down=-down;
    }
    if(up<0){//分子<0,则先输出负号,再转换为正数
        flag=1;
        printf("(-");
        up=-up;
    }
    long d=gcd(up%down,down);
    if(!up) printf("0");//分子为0
    if(up>=down) printf("%ld",up/down);//分子大于分母(假分数),需要输出假分数的整数部分
    if(up>=down&&up%down) printf(" ");//当分子大于分母,且假分数有真分数部分,输出空格
    if(up%down) printf("%ld/%ld",up%down/d,down/d);//当真分数存在,输出真分数
    if(flag) printf(")");//若为负数,补全右括号
}
long gcd(long a,long b){//求最大公约数
    return b==0?a:gcd(b,a%b);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值