当前位置: 首页 > news >正文

[PAT练级笔记] 34 Basic Level 1034 有理数四则运算

乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。

PAT乙级BasicLevelPractice 1034

问题分析

题设给定两个有理数, 要求输出这两个有理数的和、差、积、商。
如果只是这样, 则问题很简单, 但是题设要求输出的每个有理数必须是最简形式.

所以本题的一个重点是如何将有理数转为题设要求的有理数.

将有理数转为最简形式

  1. 如果分母是0
    • 非法值. 题设规定这种情况输出Inf.
  2. 如果分子是分母的倍数
    • 整数部分为 a / b
    • 分子为 0
    • 分母为 b (虽然这种情况分子分母都不输出, 但是分母为b可以用来与分母为0的情况进行区分)
  3. 如果分子不是分母的倍数
    • 求分子分母的最小公倍数 max_factor
    • 化简分子分母: a = a / max_factor; b = b / max_factor;
    • 整数部分为 a / b
    • 分子为 a % b
    • 分母为 b

有理数的加减乘除

对于有理数 a1/b1, a2/b2,
两数之和 = (a1 * b2 + a2 * b1) / (b1 * b2)
两数之差 = (a1 * b2 - a2 * b1) / (b1 * b2)
两数之积 = (a1 * a2) / (b1 * b2)
两数之商 = (a1 * b2) / (b1 * a2)

完整描述步骤

  1. 获取题设输入的有理数
  2. 计算并存储两个有理数的最简形式
  3. 计算并存储两个有理数的和、差、积、商
  4. 计算并储存和、差、积、商的最简形式
  5. 打印有理数和、差、积、商的表达式

伪代码描述

  1. get input of two rational: a1, b1, a2, b2;
  2. convert_to_most_precise_form(a1, b1, form1);
    convert_to_most_precise_form(a2, b2, form2);
  3. calculate sum, difference, product, quotient;
    convert_to_most_precise_form(a1 * b2 + a2 * b1, b1 * b2, sum);
    convert_to_most_precise_form(a1 * b2 - a2 * b1, b1 * b2, difference);
    convert_to_most_precise_form(a1 * a2, b1 * b2, product);
    convert_to_most_precise_form(a1 * b2, b1 * a2, quotient);
  4. print expression of sum, difference, product, quotient:
    print form1 + form2 = sum;
    print form1 - form2 = difference;
    print form1 * form2 = product;
    print form1 / form2 = quotient;

【题目的坑】
"题目保证正确的输出中没有超过整型范围的整数"说的是化简后的数值, 化简前的数值并没有保证不超过整型范围。
所以对于静态类型语言, 比如C/C++, 用int会在某个测试点出错, 需要把类型都换成long long

完整提交代码

/*
# 问题分析
题设给定两个有理数, 要求输出这两个有理数的和、差、积、商。
如果只是这样, 则问题很简单, 但是题设要求输出的每个有理数必须是最简形式.
所以本题的一个重点是如何将有理数转为题设要求的有理数.

# 将有理数转为最简形式
1. 如果分母是0
    - 非法值. 题设规定这种情况输出Inf.
2. 如果分子是分母的倍数
    - 整数部分为 a / b
    - 分子为 0
    - 分母为 b (虽然这种情况分子分母都不输出, 但是分母为b可以用来与分母为0的情况进行区分)
3. 如果分子不是分母的倍数
    - 求分子分母的最小公倍数 max_factor
    - 化简分子分母: a = a / max_factor; b = b / max_factor;
    - 整数部分为 a / b
    - 分子为 a % b
    - 分母为 b

# 有理数的加减乘除
对于有理数 a1/b1, a2/b2,
两数之和 = (a1 * b2 + a2 * b1) / (b1 * b2)
两数之差 = (a1 * b2 - a2 * b1) / (b1 * b2)
两数之积 = (a1 * a2) / (b1 * b2)
两数之商 = (a1 * b2) / (b1 * a2)

# 完整描述步骤
1. 获取题设输入的有理数
2. 计算并存储两个有理数的最简形式
3. 计算并存储两个有理数的和、差、积、商
4. 计算并储存和、差、积、商的最简形式
5. 打印有理数和、差、积、商的表达式

# 伪代码描述
1. get input of two rational: a1, b1, a2, b2;
2. convert_to_most_precise_form(a1, b1, form1);
    convert_to_most_precise_form(a2, b2, form2);
3. calculate sum, difference, product, quotient;
    convert_to_most_precise_form(a1 * b2 + a2 * b1, b1 * b2, sum);
    convert_to_most_precise_form(a1 * b2 - a2 * b1, b1 * b2, difference);
    convert_to_most_precise_form(a1 * a2, b1 * b2, product);
    convert_to_most_precise_form(a1 * b2, b1 * a2, quotient);
4. print expression of sum, difference, product, quotient:
    print form1 + form2 = sum;
    print form1 - form2 = difference;
    print form1 * form2 = product;
    print form1 / form2 = quotient;

【题目的坑】
"题目保证正确的输出中没有超过整型范围的整数"说的是化简后的数值, 化简前的数值并没有保证不超过整型范围。
所以对于静态类型语言, 比如C/C++, 用int会在某个测试点出错, 需要把类型都换成long long

*/

#include <stdio.h>

long long find_max_common_factor(long long a, long long b)
{
    return b == 0 ? a : find_max_common_factor(b, a % b);
}

void convert_to_most_precise_form(long long a, long long b, long long *result)
{
    /*
    功能: 将给定的有理数转为最简形式
    输入: a - 分子, b - 分母, result - 最简形式存储数组, 三元组存储
    描述:
        1. 检查并存储正负号
        2. 处理特殊情况: 分母为0 -> result中的3个元素都置为0
        3. 如果分子是分母的倍数 -> result = [a / b * sign, 0, b]
            否则: result = [a / b * sign, a % b, b]
                (如果a < b, 即result[0] == 0, 用result[1]表示正负号)
    */
    long long sign = 1;
    if (a < 0)
    {
        sign = -sign;
        a = -a;
    }
    if (b < 0)
    {
        sign = -sign;
        b = -b;
    }

    if (b == 0)
    {
        result[0], result[1], result[2] = 0, 0, 0;
        return;
    }

    if (a % b == 0)
    {
        result[0] = a / b * sign;
        result[1] = 0;
        result[2] = b;
        return;
    }

    long long max_factor = find_max_common_factor(a, b);
    a = a / max_factor;
    b = b / max_factor;
    result[0] = a / b * sign;
    result[1] = a % b;
    result[2] = b;
    if (result[0] == 0)
    {
        result[1] *= sign;
    }
}

void print_item(long long *item)
{
    if (item[0] < 0 || item[1] < 0)
    {
        printf("(");
    }
    if (item[0] != 0)
    {
        printf("%d", item[0]);
    }
    if (item[1] != 0 || item[0] == 0)
    {
        if (item[0] != 0)
            printf(" ");

        printf("%d", item[1]);
    }
    if (item[1] != 0)
    {
        printf("/%d", item[2]);
    }
    if (item[0] < 0 || item[1] < 0)
    {
        printf(")");
    }
}

void print_express(long long *a, long long *b, long long *c, char operator)
{
    print_item(a);
    printf(" %c ", operator);
    print_item(b);
    printf(" = ");
    if (operator== '/' && c[2] == 0)
    {
        printf("Inf");
    }
    else
    {
        print_item(c);
    }
    printf("\n");
}

long long main()
{
    long long a1, b1;
    long long a2, b2;
    scanf("%lld/%lld %lld/%lld", &a1, &b1, &a2, &b2);
    long long form1[3] = {0};
    long long form2[3] = {0};
    convert_to_most_precise_form(a1, b1, form1);
    convert_to_most_precise_form(a2, b2, form2);

    long long sum[3], difference[3], product[3], quotient[3];
    convert_to_most_precise_form(a1 * b2 + a2 * b1, b1 * b2, sum);
    convert_to_most_precise_form(a1 * b2 - a2 * b1, b1 * b2, difference);
    convert_to_most_precise_form(a1 * a2, b1 * b2, product);
    convert_to_most_precise_form(a1 * b2, b1 * a2, quotient);

    print_express(form1, form2, sum, '+');
    print_express(form1, form2, difference, '-');
    print_express(form1, form2, product, '*');
    print_express(form1, form2, quotient, '/');
    return 0;
}

相关文章:

  • 【探花交友】保存用户信息、上传用户头像、用户信息管理
  • ElasticSearch Client问题整理2
  • Python必知必会 os 模块详解
  • Promise系列学习
  • 线程同步的几种方式(2)
  • 第七章:面向对象编程(中级部分)
  • Redis知识-实战篇(1)
  • Pytorch搭建基本的GAN模型及训练过程
  • 3.7Docker consul的容器服务更新与发现
  • <位图(bitset)和布隆过滤器(BloomFilter)>——《C++高阶》
  • RxJava(四)-过滤操作符
  • 高级数据结构——图
  • 数据库(mysql)之事务
  • MapReduce基础入门1
  • 嵌入式系统开发笔记88:认识51微控制器系统架构
  • 分享的文章《人生如棋》
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Cumulo 的 ClojureScript 模块已经成型
  • mac修复ab及siege安装
  • ucore操作系统实验笔记 - 重新理解中断
  • webpack4 一点通
  • Webpack入门之遇到的那些坑,系列示例Demo
  • ------- 计算机网络基础
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 听说你叫Java(二)–Servlet请求
  • 为什么要用IPython/Jupyter?
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • ​2021半年盘点,不想你错过的重磅新书
  • ​决定德拉瓦州地区版图的关键历史事件
  • # Java NIO(一)FileChannel
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • $(function(){})与(function($){....})(jQuery)的区别
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (3)llvm ir转换过程
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (ZT)薛涌:谈贫说富
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (力扣)循环队列的实现与详解(C语言)
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (三)Honghu Cloud云架构一定时调度平台
  • (未解决)macOS matplotlib 中文是方框
  • (转)ABI是什么
  • (转)socket Aio demo
  • . NET自动找可写目录
  • .gitattributes 文件
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET 2.0中新增的一些TryGet,TryParse等方法