【分数的表示】
对一个分数来说,最简洁的写法就是写成假分数的形式,即无论分子比分母大或者小,都保留其原数。因此可以使用一个结构体来存储这种只有分子和分母的分数:
struct Fraction() //分数
{
int up, down; //分子、分母
}
于是就可以定义 Fraction 类型的变量来表示分数,或者定义数组来表示一堆分数。其中需要对这种表示制订三项规则:
- 使 down 为非负数。如界分数为负,那么令分子 up 为负即可。
- 如果该分数恰为0,那么规定其分子为0,分母为1
- 分子和分母没有除了1以外的公约数。
【分数的化简】
分数的化简主要用来 使 Fraction 变量满足分数表示的三项规定,因此化简步骤也分为以下三步:
- 如果分母 down 为负数,那么令分子 up 和分母 down 都变为相反数。
- 如果分子 up 为0,那么令分母 down 为1。
- 约分:求出分子绝对值与分母绝对值的最大公约数d,然后令分子分母同时除以d。
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 //如果分子不为0,进行约分
{
int d = gcd(abs(result.up), abs(result.down)); //分子分母的最大公约数
result.up /= d; //约去最大公约数
result.down /= d;
}
return result;
}
【分数的加法】
对两个分数 f1 和 f2,其加法计算公式为:
Fraction add(Fraction f1, Fraction f2) //分数f1加上分数f2
{
Fraction result;
result.up = f1.up*f2.down + f2.up*f1.down;
result.down = f1.down*f2.down;
return reduction(result); //返回结果分数,注意化简
}
【分数的减法】
对两个分数 f1 和 f2,其减法计算公式为:
Fraction minu(Fraction f1, Fraction f2) //分数f1减去分数f2
{
Fraction result;
result.up = f1.up*f2.down - f2.up*f1.down;
result.down = f1.down*f2.down;
return reduction(result); //返回结果分数,注意化简
}
【分数的乘法】
对两个分数 f1 和 f2,其乘法计算公式为:
Fraction multi(Fraction f1, Fraction f2) //分数f1乘以分数f2
{
Fraction result;
result.up = f1.up*f2.up;
result.down = f1.down*f2.down;
return reduction(result); //返回结果分数,注意化简
}
【分数的除法】
对两个分数 f1 和 f2,其除法计算公式为:
Fraction divide(Fraction f1, Fraction f2) //分数f1除以分数f2
{
Fraction result;
result.up = f1.up*f2.down;
result.down = f1.down*f2.up;
return reduction(result); //返回结果分数,注意化简
}
- 除法有额外注意事项。如果读入的除数为0 (只需判断 f2.up 是否为0),那么应当直接特判输出题目要求的输出语句(例如输出 Error、Inf 之类)。只有当除数不为0时,才能用上面的函数进行计算。
【分数的输出】
分数的输出根据题目的需要根据题目的要求进行,但是大体上有以下几个注意点:
- 输出分数前,需要先对其进行化简。
- 如果分数 r 的分母 down 为1,说明该分数是整数,一 般来说题目会要求直接输出分子,而省略分母的输出。
- 如果分数 r 的分子 up 的绝对值大于分母down,说明该分数是假分数,此时应按带分数的形式输出,即整数部分为 r.up/r.down,分子部分为 abs(r.up) % r.down,分母部分为 r.down
- 以上均不满足时说明分数 r 是真分数,按原样输出即可。
以下是一个输出示例:
void showResult(Fraction r)
{
r = reduction(r);
if(r.down==1)
printf("%lld",r.up);
else if(abs(r.up)>r.down)
printf("%d %d/%d",r.up/r.down, abs(r.up)%r.down, r.down);
else
printf("%d/%d",r.up, r.down);
}
强调一点:由于分数的乘法和除法的过程中可能使分子或分母超过 int 型表示范围,因此一般情况下,分子和分母应当使用 long long 型来存储。