最大公約数の求め方

 最大公約数(greatest common measure)を求める方法として、便利なのがユークリッドの互除法です。

1.アルゴリズム

 ユークリッドの互除法によれば以下の手順で二つの整数の最大公約数が計算できます。

@整数 A と B の最大公約数を求めたい時、まずA をB で割りその余りが R になったとする。
 A = B * Q + R ( Q は A をB で割った商)

AR が0なら Bが最大公約数。 R が0でないなら、BをR で割る。そのとき商がQ1、余りがR1になったとする
 B = R*Q1 + R1

Bこのように (割る数) ÷( 余り)の計算を、余りが0になるまで繰り返す。余りが0になった時の割る数が 最大公約数になる。

2.プログラム

 以上の計算方法にもとづいたプログラムを以下にのせます。プログラムはC++ でかいてあります。
 関数 CalcGCM_Float_OutPut が上に書いた計算手順で最大公約数を計算している部分です。
 GCM_OutPut は計算する整数の入力や結果の出力をおこなっている部分です。

#include <iostream>

using namespace std;  //introduces namespace std

/*                    Function Prototype                         */
int   GCM_OutPut( void ) ; //最大公約数の計算
int     CalcGCM_Float_OutPut( double , double ,double* ) ; //最大公約数計算本体

int  main( void )
{
     int  the_flag = 1 ;
 
        while( the_flag ){
          GCM_OutPut() ;
          cout<<"計算を続けますか? Yes --> 1 No --> 0 : " ;
          cin>>the_flag ;
        }

     return 0;
}

/*
  下の関数を使った最大公約数の計算とその過程の表示
 
  整数の最大公約数の計算をおこなう。実数も計算可能だが結果は保証しない
*/
int    GCM_OutPut( void )
{
     double nume ,denomi ,gcm_num ;
     double abs_nume ,abs_denomi ; //絶対値
     int one_letter ;
 
     cout<<"最大公約数を計算したい二つの整数を入力してください。:\n" ;
     cin>>nume>>denomi ;
 
     /*  入力ストリーム中に残った文字(改行まで)を取り除く[cin.ignoreでは失敗した]*/
     while( ( one_letter = getc( stdin ) ) !='\n' )  //入力ストリーム中の文字を取り除く
        ; //中身なし
 
     /*  エラー処理   */
     if( !cin ){
         cout<<"入力数値の型が正しくありません。\n" ;
         cin.clear() ; //正常状態に戻す
         return -1 ;
     }
 
     //値の絶対値をつくる
     if( nume >= 0 )
           abs_nume = nume ;
     else
           abs_nume = -1*nume ;
 
     if( denomi >= 0 )
           abs_denomi = denomi ;
     else
           abs_denomi = -1*denomi ;
 

     if( abs_nume==1 || abs_denomi==1 ){
       cout<<"1 ,-1 以外の数を入力してください。\n" ;
       return 0 ;//エラー発生呼び出しがわに返す
     }
 
     if( nume==0 || denomi==0 ){
       cout<<"0以外の数を入力してください。\n" ;
       return -2 ;//エラー発生呼び出しがわに返す
     }
 
     cout<<"ユークリッドの互除法によって"<<nume<<"と"<<denomi<<"の最大公約数を計算する\n" ;
     cout<<"割る数÷余りの計算を余りが0になるまで繰り返す。余りが0になった時の割る数が最大公約数である。\n" ;

     if( CalcGCM_Float_OutPut( abs_nume , abs_denomi  , &gcm_num ) ){
       cout<<"よって最大公約数は"<< gcm_num <<"\n" ;
     }
     else{
       cout<<"割る数が1になったので公約数は存在しない。\n" ;
     }
 
     //次の出力との区切り
     cout<<"\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" ;
 
     return 1;
}

/*
    ユークリッドの互除法によって二つの実数(nume ,denomi)の
    最大公約数(*gcm_num)を求める
 
    公約数が存在しない時は0を返す。
 
    計算の過程を表示する
    numeまたはdenomiが1の場合は使えないので、この関数を呼び出す前に処理する
 
    << Notice! >>
    fmod使うためにはstd::をつけるかプログラム内で
         using namespace std
    の宣言を要する
*/
int    CalcGCM_Float_OutPut( double nume , double denomi ,double *gcm_num )
{
     double   remain_num ; //remainder(余り)
     int      ans_calc ;   //割った商
     int      roop = 1 ;   //繰り返しループ制御変数
     int      judge_num = 0 ;  //公約数のあるなしを返す
 
     while( roop ){
 
        ans_calc = nume /denomi ;
        remain_num = fmod( nume, denomi) ;
 
        cout<<nume<<" / "<<denomi<<" = "<<ans_calc<<"..."<<remain_num<<"\n" ;
 
        if( remain_num != 0 ){
 
          nume = denomi ;
          denomi = remain_num ;
 
        }
        else
          roop = 0 ;
 
     }//whileループの終端
 
     *gcm_num = denomi ;//割り切れた時のdenomiを返す
 
     if( denomi !=1) judge_num = 1 ;//denomiが1以外なら最大公約数が求まった

    return  judge_num ;

}


数学アルゴリズムへ戻ります