1.2.16

1.2.16 #

解答 #

JAVA 版本参考:http://algs4.cs.princeton.edu/12oop/Rational.java.html

欧几里得算法仅适用于正整数,使用前需要注意。

用欧几里得算法找到公因子之后直接化简即可。

代码 #

public class Rational
{
    public long Numerator { get; }
    public long Denominator { get; }
    private readonly bool _isNegative;

    /// <summary>
    /// 构造一个有理数对象,自动变为最简形式。
    /// </summary>
    /// <param name="numerator">分子。</param>
    /// <param name="denominator">分母。</param>
    /// <exception cref="ArgumentException">分母为 0 时抛出</exception>
    public Rational(long numerator, long denominator)
    {
        if (denominator == 0)
            throw new ArgumentException("Denominator cannot be 0");

        if (numerator < 0 && denominator < 0)
        {
            _isNegative = false;
            numerator = -numerator;
            denominator = -denominator;
        }
        else if (numerator < 0 || denominator < 0)
        {
            _isNegative = true;
        }
        else
        {
            _isNegative = false;
        }

        var gcd = Gcd(Math.Abs(numerator), Math.Abs(denominator));
        if (gcd != 1)
        {
            numerator /= gcd;
            denominator /= gcd;
        }
        Numerator = numerator;
        Denominator = denominator;
    }

    /// <summary>
    /// 将两个有理数对象相加,返回一个有理数。
    /// </summary>
    /// <param name="b">加数。</param>
    /// <returns></returns>
    public Rational Plus(Rational b)
    {
        var result = new Rational(Numerator * b.Denominator + b.Numerator * Denominator, Denominator * b.Denominator);
        return result;
    }

    /// <summary>
    /// 以当前对象为被减数,减去一个有理数。
    /// </summary>
    /// <param name="b">减数。</param>
    /// <returns></returns>
    public Rational Minus(Rational b)
    {
        var result = new Rational(Numerator * b.Denominator - b.Numerator * Denominator, Denominator * b.Denominator);
        return result;
    }

    /// <summary>
    /// 将两个有理数对象相乘。
    /// </summary>
    /// <param name="b">乘数。</param>
    /// <returns></returns>
    public Rational Multiply(Rational b)
    {
        var result = new Rational(Numerator * b.Numerator, Denominator * b.Denominator);
        return result;
    }

    /// <summary>
    /// 以当前有理数为被除数,除以一个有理数。
    /// </summary>
    /// <param name="b">除数。</param>
    /// <returns></returns>
    public Rational Divide(Rational b)
    {
        var result = new Rational(Numerator * b.Denominator, Denominator * b.Numerator);
        return result;
    }

    /// <summary>
    /// 求两个正整数的最大公约数。
    /// </summary>
    /// <param name="a">第一个整数。</param>
    /// <param name="b">第二个整数。</param>
    /// <returns></returns>
    private long Gcd(long a, long b)
    {
        if (b == 0)
            return a;
        return Gcd(b, a % b);
    }

    public override bool Equals(object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (obj.GetType() != GetType())
            return false;

        var that = (Rational)obj;
        return (Numerator == that.Numerator) && (Denominator == that.Denominator);
    }

    public override int GetHashCode()
    {
        return 31 * Numerator.GetHashCode() + Denominator.GetHashCode();
    }

    /// <summary>
    /// 返回形如 “分子/分母” 的字符串
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        var result = "";
        if (_isNegative)
            result += "-";
        result += Math.Abs(Numerator) + "/" + Math.Abs(Denominator);
        return result;
    }
}