reduction関数を簡潔にしてみた
今までの奴は下記のもの。
// 約分 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 ); unsigned int counter=0; int save_index = 0; for( int i = 0; i < (int)n_factor.size(); ++i ) { for( int j = 0; j < (int)d_factor.size(); ++j ) { std::cout << counter << " - " << n_factor.at(i) << ":" << d_factor.at(j) << std::endl; ++counter; 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 ); }
下記のmain.cppを実行すると142回ループを実行する
// main.cpp #include "Friction.h" int main() { TFriction<int> a( 2*3*4*5, 6*7*8 ), b( 5*6*16, 6*30*2 ), c; c = a / b; c.Disp(); return 0; }
まずは簡単にbreakつけたもので先ほどのmain.cppを実行すると、ループは79回だった。
勿論、答えは同じ15/56になる。
// 約分 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 ); unsigned int counter=0; int save_index = 0; for( int i = 0; i < (int)n_factor.size(); ++i ) { for( int j = 0; j < (int)d_factor.size(); ++j ) { std::cout << counter << " - " << n_factor.at(i) << ":" << d_factor.at(j) << std::endl; ++counter; if( n_factor.at(i) == d_factor.at(j) ) { n_factor.at(i) = d_factor.at(j) = 1; break; } } } 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 ); }
新しいものは下記のものになる。
同じくmain.cppを実行すると、ループは14回になる。勿論、結果は15/56になっている。
これは、既に素因数分解された要素が昇順(小から大の順番に並ぶ)にソートされていることからくる(降順は大から小の順番に並ぶ)。
もっと早い方法があるかは完成後に取っておく。
加減乗除の演算子を使うたびに約分するか、operator=で一括するか。
どっちがよいだろうか。
// 約分 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 ); unsigned int counter=0; int j = 0, save_index = 0; for( int i = 0; i < (int)n_factor.size(); ++i ) { j = save_index; while( j < (int)d_factor.size() ) { std::cout << counter << " - " << n_factor.at(i) << ":" << d_factor.at(j) << std::endl; ++counter; if( n_factor.at(i) == d_factor.at(j) ) { n_factor.at(i) = d_factor.at(j) = 1; save_index = j+1; break; } ++j; } } 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 ); }