bate's blog

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

さらに汚く

いつも思うが、もう少し賢く整理の上手い人間だったならと。心の底から。
まずは、Friction.hというファイル。

// Friction.cpp

#ifndef __FRICTION_H__
#define __FRICTION_H__


#include <iostream>
#include "Function.h"


// 分数
template <class T>
class TFriction
{
private:
	T m_numerator;		// 分子
	T m_denominator;	// 分母
	
	bool m_sign;		// 符号(true:+,false:-)

public:
	TFriction( T nu=0, T de=1 )
	: m_numerator( nu ), m_denominator( de ), m_sign( 1 )
	{ }

	~TFriction()
	{ }

	T GetNumerator()
	{
		return m_numerator;
	}
	T GetDenominator()
	{
		return m_denominator;
	}
	void SetNumerator( T n )
	{
		m_numerator = n;
	}
	void SetDenominator( T d )
	{
		m_denominator = d;
	}

	bool GetSign()
	{
		return m_sign;
	}

	void Disp();
	void Sign();
	void Exec();

	TFriction<T> reduction();

	// 演算子
	TFriction<T>& operator=( TFriction<T> t )
	{
		m_numerator = t.GetNumerator();
		m_denominator = t.GetDenominator();
		m_sign = t.GetSign();

		return *this;
	}

	TFriction<T> operator+( TFriction<T> t )
	{
		this->Exec();
		t.Exec();

		TFriction<T> temp( t.GetDenominator()*this->m_numerator
						+ this->m_denominator*t.GetNumerator(),		// 分子
						this->m_denominator * t.GetDenominator()	// 分母
						);
		
		temp = temp.reduction(); 

		return temp;
	}
};

// 約分
template<class T> TFriction<T> TFriction<T>::reduction()
{
	Exec();

	// 負の符号の時は、分子から負を取り因数分解する
	if( false == m_sign )
		m_numerator *= -1;

	std::vector<T> n_factor = Factorization<T>( m_numerator );
	std::vector<T> d_factor = Factorization<T>( m_denominator );

	for( int i = 0; i < (int)n_factor.size(); ++i )
	{
		for( int j = 0; j < (int)d_factor.size(); ++j )
		{
			std::cout << n_factor.at(i) << ":" << d_factor.at(j) << std::endl;
			if( n_factor.at(i) == d_factor.at(j) )
				n_factor.at(i) = d_factor.at(j) = 1;
		}
	}
	
	T num = 1;
	T den = 1;
	for( int i = 0; i < (int)n_factor.size(); ++i )
		num *= n_factor.at(i);
	for( int j = 0; j < (int)d_factor.size(); ++j )
		den *= d_factor.at(j);

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

	return TFriction<T>( num, den );
}




template<class T> void TFriction<T>::Sign()
{
	int i = ( m_numerator < 0 ) ? 0 : 1;
	int j = ( m_denominator < 0 ) ? 0 : 1;
	m_sign = ( i ^ j ) ? 0 : 1;
}

template<class T> void TFriction<T>::Exec()
{
	Sign();
	// 符号を分子に
	if( m_denominator < 0 )
	{
		m_numerator *= -1;
		m_denominator *= -1;
	}
}


template<class T> void TFriction<T>::Disp()
{
	Exec();

	std::cout << m_numerator << "/" << m_denominator << std::endl;
}


#endif	// __FRICTION_H__

次に、Function.hというファイル。

// Function.h

#ifndef __FUNCTION_H__
#define __FUNCTION_H__

#include <vector>


//-----------------------------------------------
// 前宣言
//-----------------------------------------------
// 最大公約数を返す
template<class T> T gcd( T m, T n );
// 因数分解のベクターを返す
template<class T> std::vector<T> Factorization( T n );


//-----------------------------------------------
// 実装
//-----------------------------------------------

// 最大公約数を返す
template<class T> T gcd( T m, T n )
{
	if( m < n )
		swap( m, n );

	if( 0 == n )
		return m;

	if( 0 == n % m )
		return n;

	m = m % n;
	swap( m, n );

	return gcd<T>( m, n );
}

// 因数分解
template<class T> std::vector<T> Factorization( T n )
{
	std::vector<T> factor_elements;
	T a = 2;

	while( n >= a*a )
	{
		if( 0 == n % a )
		{
			// 因数分解の要素を格納
			factor_elements.push_back( a );
			n /= a;
		}
		else
			++a;
	}

	factor_elements.push_back( n );

	return factor_elements;
}



#endif	// __FUNCTION_H__

最後に、main.cppというファイル

// main.cpp

#include "Friction.h"

int main()
{
	TFriction<int> a( 3, 5 ), b( 4, -4 ), c;
	c = a + b;
	c.Disp();
	return 0;
}


Effective C# 4.0

Effective C# 4.0