题目
You are provided with a skeleton of the class ‘Fraction’, which accepts two arguments (numerator, denominator).
EXAMPLE:
Fraction fraction1 = new Fraction(4, 5);
Task
Your task is to make this class string representable, and addable while keeping the result in the minimum representation possible.
EXAMPLE:
Console.Write(fraction1 + new Fraction(1, 8));
// Outputs: 37/40
NB: DON’T use the built_in class ‘fractions.Fraction’
Enjoy!
解题思路
本题的重点是fraction——对分数的理解。该分数有两个arguments。我们的任务是实现分数加法和最简化。不允许我们使用fraction方法(因为是让我们自己来实现这个方法)。那么:
- 如何实现分数最简化?
- 如何实现分数的加法?
我们可以先看第二个问题,分数的加法,假设两个分数a、b分别是x1/y1和x2/y2,那么一定能得出它们的和是(x1y2+x2y1)/y1*y2。
然后要做的就是如何化简这个式子,最简形式说明已经除去了分子分母的公约数。我们让它分子分母把每一个同时小于分子分母的数,一个一个都除一下(包括分子分母本身),直到再也除不了了就是最简形式。
最后,我们需要考虑按题意输出题目所需要的字符串。我们可以重写string方法。
代码
public class Fraction
{
private long Top { get; set; }
private long Bottom { get; set; }
public Fraction(long numerator, long denominator)
{
Top = numerator;
Bottom = denominator;
}
// Equality checking
public override int GetHashCode() => this.GetHashCode(); // not actually used
public override bool Equals(object o) => Compare(this, o as Fraction) == 0;
public static bool operator ==(Fraction f1, Fraction f2) => Compare(f1, f2) == 0;
public static bool operator !=(Fraction f1, Fraction f2) => Compare(f1, f2) != 0;
private static long Compare(Fraction f1, Fraction f2) => f1.Top * f2.Bottom - f2.Top * f1.Bottom;
//重写string方法
public override string ToString(){
return this.Top+"/"+this.Bottom;
}
//运算符重载,以便直接使用+来测试
public static Fraction operator+ (Fraction a,Fraction b) {
return Add(a,b);
}
// 实现两个分数a、b的加法,用m、n来表示a+b的和
public static Fraction Add(Fraction a,Fraction b){
long m=a.Top*b.Bottom+a.Bottom*b.Top;
long n=a.Bottom*b.Bottom;
//利用循环,让分子分母同时除以i,这里的i则是一定不大于m、n的数,,从2开始除是因为除以1或0没意义
for(int i = 2; i<=n&&i<=m;){
if(m%i==0&&n%i==0){
m/=i;
n/=i;//如果除得尽,m、n相当于化简了一次,i要变回2
}
else{//当发现除不尽的时候,就将i增加1,相当于换一个数来除,看能不能刚好除得尽
i++;
}
}
//实现分数的加法
var sum = new Fraction(m,n);
return sum;
}
}