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;
}
}