bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

C#で要素が分数の行列

これまでに書いたコード。

Class1.cs

using System;
using MyMath;

namespace ConsoleApplication2
{
	/// <summary>
	/// Class1 の概要の説明です。
	/// </summary>
	class Class1
	{
		/// <summary>
		/// アプリケーションのメイン エントリ ポイントです。
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			Fraction a = new Fraction( 1, -2 );
			Fraction zero = new Fraction( 0, 1 );

			Fraction[,] Array = new Fraction[2,2];
			for( int i = 0; i < 2; ++i )
				for( int j = 0; j < 2; ++j )
					if( i == j )
						Array[i, j] = a;
					else
						Array[i, j] = zero;

			Matrix m = new Matrix( Array );
			m.Disp();
			m = m.Inverse();
			m.Disp();
		}
		// End of Main()
	}
}

Function.cs

using System;
using System.Collections;

namespace MyMath
{
	/// <summary>
	/// 関数
	/// </summary>
	public class Function
	{
		public static ArrayList Factorization( int n )
		{
			ArrayList factor_elements = new ArrayList();
			int a = 2;

			while( n >= a*a )
			{
				if( 0 == n % a )
				{
					factor_elements.Add( a );
					n /= a;
				}
				else
					++a;
			}
			factor_elements.Add( n );

			return factor_elements;
		}
	}
}

Fraction.cs

using System;
using System.Collections;

namespace MyMath
{
	/// <summary>
	/// 分数クラスです。
	/// </summary>
	public class Fraction
	{
		private int m_numerator;
		private int m_denominator;
		private int m_sign;	// +:1, -:0

		// コンストラクタ
		public Fraction( int num, int dem )
		{
			this.m_numerator = num;
			this.m_denominator = dem;

			Sign();
		}

		public Fraction() : this( 0, 1 )
		{
			Sign();
		}

		~Fraction()
		{ }

		public int GetNumerator()
		{
			return this.m_numerator;
		}
		public int GetDenominator()
		{
			return this.m_denominator;
		}
		public void SetNumerator( int num )
		{
			this.m_numerator = num;
		}
		public void SetDenominator( int den )
		{
			this.m_denominator = den;
		}

		public override string ToString()
		{
			//return ( this.m_numerator + "/" + this.m_denominator );
			return ( string.Format( "{0}/{1}", this.m_numerator, this.m_denominator ) );
		}
		public void Disp()
		{
			Console.WriteLine( "{0}/{1}", m_numerator, m_denominator );
		}

		// 符号について
		public void Sign()
		{
			// 符号を分子に
			if( this.m_denominator < 0 )
			{
				this.m_numerator *= -1;
				this.m_denominator *= -1;
			}

			// +:1, -:0
			this.m_sign = ( ( this.m_numerator < 0 ) ? 0 : 1 );
		}

		// 約分
		public Fraction Reduction()
		{
			Sign();

			if( 0 == m_sign )
				m_numerator *= -1;

			// 分子が0なら計算しない
			if( 0 == m_numerator )
			{
				m_denominator = 1;
				return new Fraction( m_numerator, m_denominator );
			}

			ArrayList n_factor = Function.Factorization( m_numerator );
			ArrayList d_factor = Function.Factorization( m_denominator );

			int j = 0, save_index = 0;
			for( int i = 0; i < n_factor.Count; ++i )
			{
				j = save_index;
				while( j < d_factor.Count )
				{
					if( (int)n_factor[i] == (int)d_factor[j] )
					{
						n_factor[i] = d_factor[j] = 1;
						save_index = j+1;

						break;
					}

					++j;
				}
			}

			int num = 1;
			int den = 1;
			for( int i = 0; i < n_factor.Count; ++i )
				num *= (int)n_factor[i];
			for( int i = 0; i < d_factor.Count; ++i )
				den *= (int)d_factor[i];

			if( 0 == m_sign ) num *= -1;

			return new Fraction( num, den );

		}

		// 演算子
		public static Fraction operator+( Fraction a, Fraction b )
		{
			Fraction t = new Fraction(
				a.GetNumerator()*b.GetDenominator() + a.GetDenominator()*b.GetNumerator(),
				a.GetDenominator()*b.GetDenominator()
				);
			t = t.Reduction();
			return t;
		}

		public static Fraction operator-( Fraction a, Fraction b )
		{
			Fraction t =new Fraction(
				a.GetNumerator()*b.GetDenominator() - b.GetNumerator()*a.GetDenominator(),
				a.GetDenominator()*b.GetDenominator()
				);
			t = t.Reduction();
			return t;
		}

		public static Fraction operator*( Fraction a, Fraction b )
		{
			Fraction t = new Fraction(
				a.GetNumerator()*b.GetNumerator(),
				a.GetDenominator()*b.GetDenominator()
				);
			t = t.Reduction();
			return t;
		}

		public static Fraction operator/( Fraction a, Fraction b )
		{
			Fraction t = new Fraction(
				a.GetNumerator()*b.GetDenominator(),
				a.GetDenominator()*b.GetNumerator()
				);
			t = t.Reduction();
			return t;
		}
	}
}

Matrix.cs

				for( int j = 0; j < this.GetColumn(); ++j )
				{
					Console.Write( "{0,6}", this[i, j] );
				}
				Console.WriteLine();
			}
		}

		// 演算子
		public static Matrix operator+( Matrix a, Matrix b )
		{
			int row = a.GetRow();
			int column = a.GetColumn();
			if( a.GetRow() < b.GetRow() )
				row = b.GetRow();
			if( a.GetColumn() < b.GetColumn() )
				column = b.GetColumn();

			Fraction[,] array = new Fraction[row,column];
			
			for( int i = 0; i < row; ++i )
				for( int j = 0; j < column; ++j )
					array[i, j] = a[i, j] + b[i, j];

			return new Matrix( array );
		}

		public static Matrix operator-( Matrix a, Matrix b )
		{
			int row = a.GetRow();
			int column = a.GetColumn();
			if( a.GetRow() < b.GetRow() )
				row = b.GetRow();
			if( a.GetColumn() < b.GetColumn() )
				column = b.GetColumn();

			Fraction[,] array = new Fraction[row,column];
			
			for( int i = 0; i < row; ++i )
				for( int j = 0; j < column; ++j )
					array[i, j] = a[i, j] - b[i, j];

			return new Matrix( array );
		}

		public static Matrix operator *( Matrix a, Matrix b )
		{
			int row = a.GetRow();
			int column = a.GetColumn();
			if( a.GetRow() < b.GetRow() )
				row = b.GetRow();
			if( a.GetColumn() < b.GetColumn() )
				column = b.GetColumn();

			Fraction[,] array = new Fraction[row,column];
			
			for( int i = 0; i < row; ++i )
				for( int j = 0; j < column; ++j )
				{
					Fraction zero = new Fraction( 0, 1 );
					array[i, j] = zero;
					for( int k = 0; k < column; ++k )
						array[i, j] += a[i, k] * b[k, j];
				}

			return new Matrix( array );
		}

		public static bool operator ==( Matrix a, Matrix b )
		{
			for( int i = 0; i < a.GetRow(); ++i )
				for( int j = 0; j < a.GetColumn(); ++j )
					if( a[i, j] != b[i, j] )
						return false;

			return true;
		}

		public static bool operator !=( Matrix a, Matrix b )
		{
			if( a == b )
				return false;

			return true;
		}

		public override bool Equals( object obj )
		{
			if( !(obj is Matrix) )
				return false;
			else
				return this == (Matrix)obj;
		}

		public override int GetHashCode()
		{
			return base.GetHashCode ();
		}


		public Matrix Inverse()
		{
			Fraction one = new Fraction( 1, 1 );
			Fraction zero = new Fraction( 0, 1 );
			// 拡大行列
			int row = this.GetRow();
			int column = this.GetColumn();
			Fraction[,] array = new Fraction[row, 2*column];
			for( int i = 0; i < row; ++i )
			{
				for( int j = 0; j < column; ++j )
				{
					array[i, j] = this.m_elements[i, j];
				}
				for( int j = column; j < 2*column; ++j )
				{
					if( (i+column) != j )
						array[i, j] = zero;
					else
						array[i, j] = one;
				}
			}

			Fraction pivot, d;
			for( int k = 0; k < row; ++k )
			{
				pivot = array[k,k];
				for( int j = k; j < 2*column; ++j )
					array[k,j] = array[k,j]/pivot;
				for( int i = 0; i < row; ++i )
				{
					if( i != k )
					{
						d = array[i,k];
						for( int j = k; j < 2*column; ++j )
							array[i,j] = array[i,j] - d * array[k,j];
					}
				}
			}

			Fraction[,] ret = new Fraction[row, column];
			for( int i = 0; i < row; ++i )
			{
				for( int j = 0; j < column; ++j )
				{
					ret[i,j] = array[i,column+j];
				}
			}

			return new Matrix( ret );
		}
	}
}