分数的四则运算

所谓的分数的四则运算是指,给定两个分数的分子和分母,求他们加减乘除的结果,先介绍如何表示和化简一个分数。

一、分数的表示和化简

  1. 分数的表示

    对于一个分数来说,最简洁的写法就是写成假分数的形式,即无论分子比分母大或者小,都保留其原数。因此可以使用一个结构体来保存这种只有分子和分母的分数:

    1
    2
    3
    struct  {   
    int up, down; //分子、分母
    };

    于是就可以定义Fraction类型的变量来表示分数,或者定义数组来表示一堆分数,其中需要对这种表达制定的三项规则:

    ①使用down为非负数。如果分数为负数那么令分子up为负即可。

    ②如果该分数恰为0, 那么规定其分子为0分母为1.

    ③分子和分母没有除了1以外的公约数。

  2. 分数的化简

    分数的化简主要使用Fraction变量满足分数表示的三项规定,因此化简步骤也分为三步:

    ①如果分母down为负数,那么令分子up和分母down都变为相反数

    ②如果分子up为0,那么令分数down为1

    ③约分:求出分子绝对值与分母绝对值的最大公约数d,然后令分子分母同时除以d;

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    #include<cmath>
    #include<algorithm>
    using namespace std;
    struct {
    int up, down;
    };

    int gcd(int a, int b) {
    if(b == 0) return a;
    else return gcd(b, a%b);
    }

    Fraction reduction(Fraction &result) {
    if(result.down < 0) { //分母为负数 令分子和分母都变为相反数
    result.up = -result.up;
    result.down = - result.down;
    }
    if(result.up == 0) { //如果分子为0
    result.down = 1; //令分母为1
    } else {
    int d = gcd(abs(result.up), abs(result.down)); //求分子与分母的最大公约数
    result.up = result.up / d;
    result.down = result.down / d;
    }
    return result;
    }

    int main() {
    Fraction a;
    scanf("%d%d", &a.up, &a.down);
    printf("%d/%dn", a.up, a.down);
    reduction(a);
    printf("%d/%dn", a.up, a.down);
    return 0;
    }

二、分数的四则运算

1.分数的加法

对于两个分数f1与f2,其加法的计算公式为
$$
result = frac{f1.upf2.down + f2.upf1.down}{f1.down*f2.down}
$$
2.分数的减法

对于两个分数f1与f2,其减法的计算公式为
$$
result = frac{f1.upf2.down - f2.upf1.down}{f1.down*f2.down}
$$
3.分数的乘法

对于两个分数f1与f2,其乘法的计算公式为
$$
result = frac{f1.upf2.up}{f1.downf2.down}
$$
4.分数的除法

对于两个分数f1和f2,其除法的计算公式为
$$
result = frac{f1.upf2.down}{f1.downf2.up}
$$
做除法的时候应要额外注意 如果输出的除数为0只需要判断f2.up是否为0,那么应当直接特判输出题目要求的语句。只有除数不为0的时候才能够用上面的函数进行输出。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

#include<cmath>
#include<algorithm>
using namespace std;
struct {
int up, down;
};

int gcd(int a, int b) {
if(b == 0) return a;
else return gcd(b, a%b);
}

Fraction reduction(Fraction &result) {
if(result.down < 0) { //分母为负数 令分子和分母都变为相反数
result.up = -result.up;
result.down = - result.down;
}
if(result.up == 0) { //如果分子为0
result.down = 1; //令分母为1
} else {
int d = gcd(abs(result.up), abs(result.down)); //求分子与分母的最大公约数
result.up = result.up / d;
result.down = result.down / d;
}
return result;
}

Fraction add(Fraction f1, Fraction f2) { //加法
Fraction result;
result.up = f1.up * f2.down + f2.up * f1.down; //分数和的分子
result.down = f1.down * f2.down; //分数和的分母
return reduction(result);
}

Fraction minu(Fraction f1, Fraction f2) { //减法
Fraction result;
result.up = f1.up * f2.down - f2.up * f1.down; //分数和的分子
result.down = f1.down * f2.down; //分数和的分母
return reduction(result);
}

Fraction multi(Fraction f1, Fraction f2) { //乘法
Fraction result;
result.up = f1.up * f2.up; //分数积的分子
result.down = f1.down * f2.down;
return reduction(result);
}

Fraction divide(Fraction f1, Fraction f2) {
Fraction result;
result.up = f1.up * f2.down;
result.down = f1.down * f2.up;
return reduction(result);
}

int main() {
Fraction a, b, c;
scanf("%d%d%d%d", &a.up, &a.down, &b.up, &b.down);
c = add(a, b);
printf("%d/%dn", c.up, c.down);
c = minu(a, b);
printf("%d/%dn", c.up, c.down);
c = multi(a, b);
printf("%d/%dn", c.up, c.down);
if(b.up == 0) { //保证了分母不为0
printf("error!n");
} else {
c = divide(a, b);
printf("%d/%dn", c.up, c.down);
}

return 0;
}

输入:

1
1 2 1 3

输出:

1
2
3
4
5/6
1/6
1/6
3/2

三、分数的输出

分数的输出根据题目的要求进行,但是大体上有以下几个注意点:

①输出分数前,需要对其进行化简

②如果分数r的分母down为1,说明该分数是整数,一般来说题目会要求直接输出分子而省略分母的输出

③如果分数r的分子up的绝对值大于分母down,说明应该是假分数,这时候应该以带分数的形式输出,即整数部分为r.up/r.down 而分子部分为abs(r.up) % r.down 分母部分为r.down

1
2
3
4
5
6
7
8
9
void showResult(Fraction r) {
r = reduction(r);
if(r.down == 1) printf("%lld", r.up); //整数
else if(abs(r.up) < abs(r.down)) {
printf("%d/%dn", r.up, r.down);
} else {
printf("%d %d/%d", r.up / r.down, abs(r.up) % r.down, r.down);
}
}

强调一下:由于分数的乘法和分数的除法过程中会使用分子或分母超过int的表示范围因此一般盈亏下分子和分母应该使用long long类型来存储。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

#include<cmath>
#include<algorithm>
using namespace std;
struct {
long long up, down;
};

int gcd(int a, int b) {
if(b == 0) return a;
else return gcd(b, a%b);
}

Fraction reduction(Fraction &result) {
if(result.down < 0) { //分母为负数 令分子和分母都变为相反数
result.up = -result.up;
result.down = - result.down;
}
if(result.up == 0) { //如果分子为0
result.down = 1; //令分母为1
} else {
int d = gcd(abs(result.up), abs(result.down)); //求分子与分母的最大公约数
result.up = result.up / d;
result.down = result.down / d;
}
return result;
}

Fraction add(Fraction f1, Fraction f2) { //加法
Fraction result;
result.up = f1.up * f2.down + f2.up * f1.down; //分数和的分子
result.down = f1.down * f2.down; //分数和的分母
return reduction(result);
}

Fraction minu(Fraction f1, Fraction f2) { //减法
Fraction result;
result.up = f1.up * f2.down - f2.up * f1.down; //分数和的分子
result.down = f1.down * f2.down; //分数和的分母
return reduction(result);
}

Fraction multi(Fraction f1, Fraction f2) { //乘法
Fraction result;
result.up = f1.up * f2.up; //分数积的分子
result.down = f1.down * f2.down;
return reduction(result);
}

Fraction divide(Fraction f1, Fraction f2) {
Fraction result;
result.up = f1.up * f2.down;
result.down = f1.down * f2.up;
return reduction(result);
}

void showResult(Fraction r) {
r = reduction(r);
if(r.down == 1) printf("%lldn", r.up); //整数
else if(abs(r.up) < abs(r.down)) {
printf("%lld/%lldn", r.up, r.down);
} else {
printf("%lld %lld/%lldn", r.up / r.down, abs(r.up) % r.down, r.down);
}
}

int main() {
Fraction a, b, c;
scanf("%lld%lld%lld%lld", &a.up, &a.down, &b.up, &b.down);
c = add(a, b);
showResult(c);
c = minu(a, b);
showResult(c);
c = multi(a, b);
showResult(c);
if(b.up == 0) { //保证了分母不为0
printf("error!n");
} else {
c = divide(a, b);
showResult(c);
}

return 0;
}