zoukankan      html  css  js  c++  java
  • PTA 乙级 1034 有理数四则运算 (20分) C/C++

     坑多,坑多

    分为几个部分:

    加工:将数字化为符合格式要求的形式

    化简:使分母始终为正,分子分母化为最简(注意最大公约数为零的情况,否则可能编译无法通过,然后报浮点错误

    求最大公约数:递归利用辗转相除法求最大公约数

    加法,减法,除法,乘法运算

    辗转相除法

    1 long long gcd(long long x, long long y) {
    2     long long z = 0;
    3     while (x % y) {
    4         z = x % y;
    5         x = y;
    6         y = z;
    7     }
    8     return z;
    9 }

    注意:

    • 测试点3:
      • 用long long类型存储分子分母,题中只是说正确的输出中没有超过整形范围的整数,但乘法可能会出现超过整形范围的整数,以致测试点3报浮点错误
      • 记得考虑分子分母绝对值相等的情况,否则会报答案错误
      • 还要注意分子分母负负得正(保持分母始终为正数),否则会报答案错误    
    • 测试点2:注意用空间复杂度小的方法求最大公约数,不可以用枚举法,会超时

    C/C++

     1 #include<iostream>
     2 #include<string>
     3 
     4 using namespace std;
     5 
     6 typedef struct {
     7     /*假分数分子*/
     8     long long men;
     9     /*真分数分子*/
    10     long long rmen;
    11     /*分母*/
    12     long long den;
    13     /*真数*/
    14     long long ant;
    15     /*最终输出形式*/
    16     string s;
    17 }Num;
    18 
    19 long long gcd(long long x, long long y) {    //求最大公约数
    20     return y == 0 ? x : gcd(y, x % y);
    21 }
    22 
    23 int simplify(Num* n) {                        //化简
    24     if (n->den < 0)n->men = -(n->men), n->den = -(n->den);    //保持分母始终为正
    25     long long rem = gcd(abs(n->men), abs(n->den));
    26     if (rem == 0) return 0;                    //出现最大公约数为零的情况(没有最大公约数),直接返回
    27     n->men /= rem;
    28     n->den /= rem;
    29     return 0;
    30 }
    31 
    32 int process(Num* n) {
    33     if (n->den == 0) {                        //分母为零的情况
    34         n->s = "Inf";
    35         return 0;
    36     }
    37     simplify(n);
    38     n->ant = 0;    
    39     if ((long long)abs(n->men) >= n->den) {    //假分数(注意分子分母相等的情况,否则测试点3过不了)
    40         if (n->men % n->den == 0) {            //可以除尽,化为整数
    41             n->ant = n->men / n->den;
    42             n->s = to_string(n->ant);
    43         }
    44         else{                                //化为带分数
    45             n->ant = n->men / n->den;
    46             n->rmen = (long long)abs(n->men) - ((long long)abs(n->ant) * n->den);
    47             n->s = to_string(n->ant) + ' ' + to_string(n->rmen) + '/' + to_string(n->den);
    48         }
    49     }
    50     else if (n->men == 0) {                    //分子为零
    51         n->s = "0";
    52     }
    53     else {                                    //真分数
    54         n->s = to_string(n->men) + '/' + to_string(n->den);
    55     }                                        //负数带符号
    56     if (n->men < 0 || n->ant < 0)n->s = '(' + n->s + ')';
    57     return 0;
    58 }
    59 
    60 void plusnum(Num* x, Num* y, Num* z) {        //加法
    61     z->den = x->den * y->den;
    62     z->men = x->men * y->den + y->men * x->den;
    63     process(z);
    64 }
    65 
    66 void minusnum(Num* x, Num* y, Num* z) {        //减法
    67     z->den = x->den * y->den;
    68     z->men = x->men * y->den - y->men * x->den;
    69     process(z);
    70 }
    71 
    72 void multiplynum(Num* x, Num* y, Num* z) {    //乘法
    73     z->men = x->men * y->men;
    74     z->den = x->den * y->den;
    75     process(z);
    76 }
    77 
    78 void dividenum(Num* x, Num* y, Num* z) {    //除法
    79     z->men = x->men * y->den;
    80     z->den = x->den * y->men;
    81     process(z);
    82 }
    83 
    84 int main() {
    85     Num a, b, ret;
    86     scanf_s("%lld/%lld %lld/%lld", &a.men, &a.den, &b.men, &b.den);    //vs为scanf_s
    87     process(&a);
    88     process(&b);
    89     plusnum(&a, &b, &ret);
    90     cout << a.s << " + " << b.s << " = " << ret.s << endl;
    91     minusnum(&a, &b, &ret);
    92     cout << a.s << " - " << b.s << " = " << ret.s << endl;
    93     multiplynum(&a, &b, &ret);
    94     cout << a.s << " * " << b.s << " = " << ret.s << endl;
    95     dividenum(&a, &b, &ret);
    96     cout << a.s << " / " << b.s << " = " << ret.s << endl;
    97     return 0;
    98 }

    哈哈,还蛮快的

  • 相关阅读:
    Linux--sed命令
    Linux--cut命令
    Android--aapt命令
    Shell--基础知识
    Linux--vim编辑器和文件恢复
    Linux--基本命令
    Linux--添加用户
    Linux--网络配置
    SpringCloud--Ribbon负载均衡
    第一阶段冲刺4
  • 原文地址:https://www.cnblogs.com/SCP-514/p/13363914.html
Copyright © 2011-2022 走看看