問題
次の分数は約分できますか。できるのであれば、約分してもとっとも簡単な分数で表しなさい
\frac{10033}{12877}
ユークリッドやなーって感じの問題が数学検定1級の練習問題で出てきた次の分数は約分できますか。できるのであれば、約分してもとっとも簡単な分数で表しなさい
\frac{10033}{12877}
そういえば
ユーグリットの互除法は、プログラムだと再起関数の例題でよく見かけるが、実際組んだことなかったので
プログラムでこの問題を解いてみることにする
ユークリッドの互除法とは
これで何で最大公約数が簡単に求まるのか。実際に本問題の最大公約数を求めてみる
gcm(12877,10033)=gcm(10033,2844) | (\because12877\div10033 = 1\times 10033 + 2844) |
gcm(10033,2844)=gcm(2844,1501) | (\because10033\div2844 = 3\times 2844 + 1501) |
gcm(2844,1501)=gcm(1501,1343) | (\because2844\div1501 = 1\times 1501 + 1343) |
gcm(1501,1343)=gcm(1343,158) | (\because1501\div1343 = 1\times 1343 + 158) |
gcm(1343,158)=gcm(158,79) | (\because1343\div158 = 8\times 158 + 79) |
gcm(158,79)\ne gcm(79,0) | (\because158\div79 = 2\times 79 + 0) |
繰り返すごとに数字が小さくなっているのがわかる
これは割ったあまりを次の最大公約数を求めるために使うから、一般的な割り算の考え方(割られる数>割る数>あまり)より
繰り返すたびに数字が小さくなっていく
実装
再帰関数が使えるプログラム言語なら超簡単。2つの引数の最大公約数を求める関数はこんな感じこの関数を使って本問題を解くと
- /**
- * 2つの引数の最大公約数(gcm)をユーグリットの互除法で求める.
- * @param n1 対象の数字1
- * @param n2 対象の数字2
- * @return ret 最大公約数
- */
- int gcm(int n1, int n2) {
- int ret = n1 % n2;
- return (ret == 0) ? n2 : gcm(n2, ret);
- }
- /**
- * 約分問題を解くプログラム
- * gcm.cpp
- */
- #include<iostream>
- #include<cmath>
- /** 分子. */
- #define NUMERATOR 10033
- /** 分母. */
- #define DENOMINATOR 12877
- int gcm(int, int); // 最大公約数を求める関数(内容省略)
- int main(){
- int numerator = NUMERATOR; // 分子
- int denominator = DENOMINATOR; // 分母
- int gcm_num = gcm(numerator, denominator); // 最大公約数
- if(gcm_num == 1) {
- // 約分できない場合
- // 最大公約数「1」は互いに素の関係だから約分できない
- std::cout << " 約分できません " << std::endl;
- } else {
- // 約分できる場合
- // 約分する
- numerator /= gcm_num;
- denominator /= gcm_num;
- // 分母、分子間の線の長さを計算(対数を使って桁数取得)
- int line = (int)log10(fmax(numerator, denominator)) + 1;
- // 解表示
- std::cout << numerator << std::endl;
- for(int i = 0; i < line; i++) std::cout << "-";
- std::cout << std::endl << denominator << std::endl;
- }
- return 0;
- }
実行結果
$ g++ gcm.cpp $ ./a.out 127 --- 163約分できることがわかった
ハイライトの箇所(31,32行目)はちょっと特殊な計算で線の長さを求めてる(対数による桁数計算方法)
これについては本問題と関係ないし、また後日説明しようかな
後日説明 ⇒ 数字の桁数を取得する方法
0 件のコメント:
コメントを投稿