[C#] 分数クラスを丁寧に実装してみた

icatch_image C#
icatch_image

Introduction

C#で分数を使う機会があったので作成しました!
備忘録的に載せて置くのでご利用ください。
バグや機能要求があればコメントくださると助かります🙌

メソッド & オペレータ

🔧 コンストラクタ

シグネチャ説明
Fraction(long numerator, long denominator = 1)分子・分母を指定して分数を生成。自動で約分・符号統一を行う

📐 プロパティ

名前説明
numerator分子。設定時に符号統一や約分を行う
denominator分母。同上

🔁 公開メソッド

メソッド名説明
Reciprocal()逆数を返す
Abs()絶対値の分数を返す
ToDouble()double に変換
ToString()"分子/分母" 形式で文字列化
ToIntOrFracString()分母が1なら整数、そうでなければ分数で表示
ToDoubleString()実数として文字列表示(精度あり)

🔄 暗黙の型変換

対象型説明
int, long自動的に denominator=1 の分数として変換される
float, double10^9 倍して整数に変換して分数に変換(精度考慮)

➕ 演算子 +

  • 分数 + 数値(int, long, float, double)
  • 数値 + 分数 (int, long, float, double)
  • 分数 + 分数

➖ 演算子 -

  • 分数 – 数値(int, long, float, double)
  • 数値 – 分数(int, long, float, double)
  • 分数 – 分数
  • -Fraction(単項マイナス)

✖️ 演算子 *

  • 分数 * 数値(int, long, float, double)
  • 数値 * 分数(int, long, float, double)
  • 分数 * 分数

➗ 演算子 /

  • 分数 / 数値(int, long, float, double)
  • 数値 / 分数(int, long, float, double)
  • 分数 / 分数

≠ 比較演算子

演算子内容
==, !=等価・非等価(暗黙変換後で比較)
<, >, <=, >=CompareTo に基づく大小比較

🔢 比較メソッド / ハッシュ

メソッド説明
CompareTo(...)int, long, float, double, Fraction との大小比較
Equals(...)Fraction / object と等価かどうか判定
GetHashCode()ハッシュコード生成

実装


#pragma warning disable

using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using static System.Console;
using static System.Math;

class Fraction : IComparable<Fraction>, IEquatable<Fraction> {
	/// 内部操作用
	private long _numerator { get; set; }
	private long _denominator { get; set; }

	/// 分子 (上書き時に約分とマイナス処理)
	public long numerator {
		get => this._numerator;
		set { this._numerator = value; this.Normalize(); }
	} // end of accessor

	/// 分母 (上書き時に約分とマイナス処理)
	public long denominator {
		get => this._denominator;
		set { this._denominator = value; this.Normalize(); }
	} // end of accessor

	/// 少数からの変換用
	public const long l10_9 = 1000000000l;

	// -------------------------- Constructor  --------------------------------

	/// 分母分子で初期化 (分母を指定しなければ1)
	public Fraction(long numerator, long denominator = 1) {
		this._numerator = numerator;
		this._denominator = denominator;
		this.Normalize();
	} // end of constructor


	// -------------------------- Public Methods --------------------------------	

	/// <summary> 逆数を返す </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public Fraction Reciprocal() {
		return new Fraction(this._denominator, this._numerator);
	} // end of method

	/// <summary> 絶対値を返す </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public Fraction Abs() {
		return new Fraction(Math.Abs(this._numerator), Math.Abs(this._denominator));
	} // end of method

	/// <summary> 実数を返す </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public double ToDouble() {
		return (double)this._numerator / this._denominator;
	} // end of method

	// -------------------------- Print Method --------------------------------

	/// <summary> 基本の分数系で表示 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public override string ToString() {
		return $"{this._numerator}/{this._denominator}";
	} // end of method

	/// <summary> 可能なら整数で表示 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public string ToIntOrFracString() {
		if (this._denominator == 1) return $"{this._numerator}";
		return $"{this._numerator}/{this._denominator}";
	} // end of method

	/// <summary> 実数にして表示 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public string ToDoubleString() {
		return string.Format("{0:0.################}", (double)this._numerator / this._denominator);
	} // end of method


	// -------------------------- Private Utils --------------------------------

	/// <summary> 約分とマイナス調整、数値変動後に呼ぶ </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	private void Normalize() {
		this.ReduceFraction();
		this.NormalizeSign();
	} // end of method

	/// <summary> 約分 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	private void ReduceFraction() {
		long gcd = Fraction.Gcd(this._numerator, this._denominator);
		this._numerator /= gcd;
		this._denominator /= gcd;
	} // end of method

	/// <summary>マイナスの位置を分子に統一</summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	private void NormalizeSign() {
		if (this._denominator < 0) {
			this._numerator *= -1;
			this._denominator *= -1;
		}
	} // end of method

	/// <summary>最大公約数を計算</summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	private static long Gcd(long a, long b) {
		if (a < 0) a = -a;
		if (b < 0) b = -b;
		if (a == 1 || b == 1) return 1;

		while (a >= 1 && b >= 1) {
			if (a < b) {
				long c = a;
				a = b;
				b = c;
			}
			a %= b;
		}
		return a > b ? a : b;
	} // end of method

	/// <summary>最小公倍数を計算(longからオーバーフローを考慮して)</summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	private static long Lcm(long a, long b) {
		Int128 ab = a * b;
		ab /= Gcd(a, b);
		return (long)ab;
	} // end of method


	// -------------------------- Implicit Operator --------------------------------

	/// <summary> intからの暗黙的な型変換 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static implicit operator Fraction(int value) {
		return new Fraction(value, 1);
	} // end of method

	/// <summary> longからの暗黙的な型変換 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static implicit operator Fraction(long value) {
		return new Fraction(value, 1);
	} // end of method

	/// <summary> floatからの暗黙的な型変換 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static implicit operator Fraction(float value) {
		// 10^9倍して約分する
		return new Fraction((long)((double)value * Fraction.l10_9), Fraction.l10_9);
	} // end of method

	/// <summary> doubleからの暗黙的な型変換 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static implicit operator Fraction(double value) {
		// 10^9倍して約分する
		return new Fraction((long)(value * Fraction.l10_9), Fraction.l10_9);
	} // end of method

	// -------------------------- Operator + --------------------------------

	/// <summary> 分数同士の足し算 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(Fraction a, Fraction b) {
		// 分母を最小公倍数で通分
		long lcm = Fraction.Lcm(a._denominator, b._denominator);
		// 通分後の分子
		long an = a._numerator * (lcm / a._denominator);
		long bn = b._numerator * (lcm / b._denominator);

		return new Fraction(an + bn, lcm);
	} // end of method

	/// <summary> 分数と整数の足し算(frac + int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(Fraction a, int b) {
		return new Fraction(a._numerator + b * a._denominator, a._denominator);
	} // end of method

	/// <summary> 分数と整数の足し算(int + frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(int a, Fraction b) {
		return new Fraction(a * b._denominator + b._numerator, b._denominator);
	} // end of method

	/// <summary> 分数と整数の足し算(frac + long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(Fraction a, long b) {
		return new Fraction(a._numerator + b * a._denominator, a._denominator);
	} // end of method

	/// <summary> 分数と整数の足し算(long + frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(long a, Fraction b) {
		return new Fraction(a * b._denominator + b._numerator, b._denominator);
	} // end of method

	/// <summary> 分数と実数の足し算(frac + float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(Fraction a, float b) {
		return a + (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の足し算(float + frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(float a, Fraction b) {
		return (Fraction)a + b;
	} // end of method

	/// <summary> 分数と実数の足し算(frac + float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(Fraction a, double b) {
		return a + (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の足し算(float + frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator +(double a, Fraction b) {
		return (Fraction)a + b;
	} // end of method

	// -------------------------- Operator - --------------------------------

	/// <summary> 分数同士の引き算 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(Fraction a, Fraction b) {
		// 分母を最小公倍数で通分
		long lcm = Fraction.Lcm(a._denominator, b._denominator);
		// 通分後の分子
		long an = a._numerator * (lcm / a._denominator);
		long bn = b._numerator * (lcm / b._denominator);

		return new Fraction(an - bn, lcm);
	} // end of method

	/// <summary> 分数と整数の引き算(frac - int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(Fraction a, int b) {
		return new Fraction(a._numerator - b * a._denominator, a._denominator);
	} // end of method

	/// <summary> 分数と整数の引き算(int - frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(int a, Fraction b) {
		return new Fraction(a * b._denominator - b._numerator, b._denominator);
	} // end of method

	/// <summary> 分数と整数の引き算(frac - long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(Fraction a, long b) {
		return new Fraction(a._numerator - b * a._denominator, a._denominator);
	} // end of method

	/// <summary> 分数と整数の引き算(long - frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(long a, Fraction b) {
		return new Fraction(a * b._denominator - b._numerator, b._denominator);
	} // end of method

	/// <summary> 分数と実数の引き算(frac - float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(Fraction a, float b) {
		return a - (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の引き算(float - frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(float a, Fraction b) {
		return (Fraction)a - b;
	} // end of method

	/// <summary> 分数と実数の引き算(frac - double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(Fraction a, double b) {
		return a - (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の引き算(double - frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(double a, Fraction b) {
		return (Fraction)a - b;
	} // end of method

	/// <summary> 単項マイナス演算子 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator -(Fraction a) {
		return new Fraction(-a._numerator, a._denominator);
	} // end of method


	// -------------------------- Operator * --------------------------------

	/// <summary> 分数同士の掛け算 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(Fraction a, Fraction b) {
		return new Fraction(a._numerator * b._numerator, a._denominator * b._denominator);
	} // end of method

	/// <summary> 分数と整数の掛け算(frac * int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(Fraction a, int b) {
		return new Fraction(a._numerator * b, a._denominator);
	} // end of method

	/// <summary> 分数と整数の掛け算(int * frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(int a, Fraction b) {
		return new Fraction(a * b._numerator, b._denominator);
	} // end of method

	/// <summary> 分数と整数の掛け算(frac * long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(Fraction a, long b) {
		return new Fraction(a._numerator * b, a._denominator);
	} // end of method

	/// <summary> 分数と整数の掛け算(long * frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(long a, Fraction b) {
		return new Fraction(a * b._numerator, b._denominator);
	} // end of method

	/// <summary> 分数と実数の掛け算(frac * float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(Fraction a, float b) {
		return a * (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の掛け算(float * frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(float a, Fraction b) {
		return (Fraction)a * b;
	} // end of method

	/// <summary> 分数と実数の掛け算(frac * double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(Fraction a, double b) {
		return a * (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の掛け算(double * frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator *(double a, Fraction b) {
		return (Fraction)a * b;
	} // end of method


	// -------------------------- Operator / --------------------------------

	/// <summary> 分数同士の割り算 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(Fraction a, Fraction b) {
		return new Fraction(a._numerator * b._denominator, a._denominator * b._numerator);
	} // end of method

	/// <summary> 分数と整数の割り算(frac / int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(Fraction a, int b) {
		return new Fraction(a._numerator, a._denominator * b);
	} // end of method

	/// <summary> 分数と整数の割り算(int / frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(int a, Fraction b) {
		return new Fraction(b._numerator, a * b._denominator);
	} // end of method

	/// <summary> 分数と整数の割り算(frac / long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(Fraction a, long b) {
		return new Fraction(a._numerator, a._denominator * b);
	} // end of method

	/// <summary> 分数と整数の割り算(long / frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(long a, Fraction b) {
		return new Fraction(b._numerator, a * b._denominator);
	} // end of method

	/// <summary> 分数と実数の割り算(frac / float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(Fraction a, float b) {
		return a / (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の割り算(float / frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(float a, Fraction b) {
		return (Fraction)a / b;
	} // end of method

	/// <summary> 分数と実数の割り算(frac / double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(Fraction a, double b) {
		return a / (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の割り算(double / frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Fraction operator /(double a, Fraction b) {
		return (Fraction)a / b;
	} // end of method


	// -------------------------- Operator ==  --------------------------------

	/// <summary> 分数同士の一致比較 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(Fraction a, Fraction b) {
		return a._numerator == b._numerator && a._denominator == b._denominator;
	} // end of method

	/// <summary> 分数と整数の一致比較(frac == int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(Fraction a, int b) {
		return a._numerator == b && a._denominator == 1l;
	} // end of method

	/// <summary> 分数と整数の一致比較(int == frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(int a, Fraction b) {
		return a == b._numerator && b._denominator == 1l;
	} // end of method

	/// <summary> 分数と整数の一致比較(frac == long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(Fraction a, long b) {
		return a._numerator == b && a._denominator == 1l;
	} // end of method

	/// <summary> 分数と整数の一致比較(long == frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(long a, Fraction b) {
		return a == b._numerator && b._denominator == 1l;
	} // end of method

	/// <summary> 分数と実数の一致比較(frac == float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(Fraction a, float b) {
		return a == (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の一致比較(float == frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(float a, Fraction b) {
		return (Fraction)a == b;
	} // end of method

	/// <summary> 分数と実数の一致比較(frac == double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(Fraction a, double b) {
		return a == (Fraction)b;
	} // end of method

	/// <summary> 分数と整数の一致比較(double == frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator ==(double a, Fraction b) {
		return (Fraction)a == b;
	} // end of method

	// -------------------------- Operator !=  --------------------------------

	/// <summary> 分数同士の不一致比較 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(Fraction a, Fraction b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と整数の不一致比較(frac != int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(Fraction a, int b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と整数の不一致比較(int != frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(int a, Fraction b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と整数の不一致比較(frac != long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(Fraction a, long b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と整数の不一致比較(long != frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(long a, Fraction b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と実数の不一致比較(frac != float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(Fraction a, float b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と整数の不一致比較(float != frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(float a, Fraction b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と実数の不一致比較(frac != double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(Fraction a, double b) {
		return !(a == b);
	} // end of method

	/// <summary> 分数と整数の不一致比較(double != frac) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator !=(double a, Fraction b) {
		return !(a == b);
	} // end of method


	// -------------------------- Operator CompareTo  --------------------------------

	/// <summary> 分数同士のCompareTo </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public int CompareTo(Fraction other) {
		// 通分して比較
		return (this._numerator * other._denominator).CompareTo(this._denominator * other._numerator);
	} // end of method

	/// <summary> intとのCompareTo </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public int CompareTo(int other) {
		return this._numerator.CompareTo(other * this._denominator);
	} // end of method

	/// <summary> longとのCompareTo </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public int CompareTo(long other) {
		return this._numerator.CompareTo(other * this._denominator);
	} // end of method

	/// <summary> floatとのCompareTo </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public int CompareTo(float other) {
		return this._numerator.CompareTo(other * this._denominator);
	} // end of method

	/// <summary> doubleとのCompareTo </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public int CompareTo(double other) {
		return this._numerator.CompareTo(other * this._denominator);
	} // end of method



	// -------------------------- Operator < --------------------------------

	/// <summary> 分数同士の比較 (Fraction < Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(Fraction a, Fraction b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction < int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(Fraction a, int b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 整数と分数の比較 (int < Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(int a, Fraction b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction < long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(Fraction a, long b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 整数と分数の比較 (long < Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(long a, Fraction b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction < float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(Fraction a, float b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 実数と分数の比較 (float < Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(float a, Fraction b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction < double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(Fraction a, double b) {
		return a.CompareTo(b) < 0;
	} // end of method

	/// <summary> 実数と分数の比較 (double < Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <(double a, Fraction b) {
		return a.CompareTo(b) < 0;
	} // end of method


	// -------------------------- Operator > --------------------------------

	/// <summary> 分数同士の比較 (Fraction > Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(Fraction a, Fraction b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction > int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(Fraction a, int b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 整数と分数の比較 (int > Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(int a, Fraction b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction > long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(Fraction a, long b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 整数と分数の比較 (long > Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(long a, Fraction b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction > float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(Fraction a, float b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 実数と分数の比較 (float > Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(float a, Fraction b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction > double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(Fraction a, double b) {
		return a.CompareTo(b) > 0;
	} // end of method

	/// <summary> 実数と分数の比較 (double > Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >(double a, Fraction b) {
		return a.CompareTo(b) > 0;
	} // end of method


	// -------------------------- Operator <= --------------------------------

	/// <summary> 分数同士の比較 (Fraction <= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(Fraction a, Fraction b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction <= int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(Fraction a, int b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 整数と分数の比較 (int <= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(int a, Fraction b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction <= long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(Fraction a, long b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 整数と分数の比較 (long <= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(long a, Fraction b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction <= float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(Fraction a, float b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 実数と分数の比較 (float <= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(float a, Fraction b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction <= double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(Fraction a, double b) {
		return a.CompareTo(b) <= 0;
	} // end of method

	/// <summary> 実数と分数の比較 (double <= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator <=(double a, Fraction b) {
		return a.CompareTo(b) <= 0;
	} // end of method


	// -------------------------- Operator >= --------------------------------

	/// <summary> 分数同士の比較 (Fraction >= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(Fraction a, Fraction b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction >= int) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(Fraction a, int b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 整数と分数の比較 (int >= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(int a, Fraction b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 分数と整数の比較 (Fraction >= long) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(Fraction a, long b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 整数と分数の比較 (long >= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(long a, Fraction b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction >= float) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(Fraction a, float b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 実数と分数の比較 (float >= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(float a, Fraction b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 分数と実数の比較 (Fraction >= double) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(Fraction a, double b) {
		return a.CompareTo(b) >= 0;
	} // end of method

	/// <summary> 実数と分数の比較 (double >= Fraction) </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool operator >=(double a, Fraction b) {
		return a.CompareTo(b) >= 0;
	} // end of method


	// -------------------------- Other Common Methods  --------------------------------

	/// <summary> 分数オブジェクトとの比較 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public bool Equals(Fraction other) {
		if (other is null) return false;
		return this._numerator == other._numerator && this._denominator == other._denominator;
	} // end of method

	/// <summary> 任意のオブジェクトとの比較 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public override bool Equals(Object other) {
		if (other is Fraction frac) return this == frac;
		return false;
	} // end of method

	/// <summary> ハッシュコードの生成 </summary>
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public override int GetHashCode() {
		return HashCode.Combine(this._numerator, this._denominator);
	} // end of method

} // end of class

使用例

using System;

class Program {
	static void Main() {
		// 分数の生成
		Fraction a = new Fraction(3, 4);     // 3/4
		Fraction b = new Fraction(2);        // 2/1(整数)

		// 四則演算
		Fraction sum = a + b;                // 3/4 + 2 = 11/4
		Fraction diff = a - b;               // 3/4 - 2 = -5/4
		Fraction prod = a * b;               // 3/4 * 2 = 6/4 = 3/2(自動約分)
		Fraction quot = a / b;               // 3/4 / 2 = 3/8

		// 比較
		bool isEqual = a == new Fraction(6, 8);  // true(約分後は同じ)
		bool isLess = a < b;                    // true

		// 実数・文字列変換
		Console.WriteLine(a.ToDouble());        // 0.75
		Console.WriteLine(a.ToString());        // "3/4"
		Console.WriteLine((Fraction)1.5);       // "3/2"(float/double からも変換可)
	}
}

この記事が役に立ちましたらぜひ左下のGoodボタンをお願いします!
皆様のGoodが執筆の励みになります。

コメント

タイトルとURLをコピーしました