アルゴリズムには直接関係ないところで、while true および while (1) がやっぱり気持悪いです。 もちろんこれらはの定数式はコンパイル言語でかつ最適化がきちんと働くのであれば、コンパイル時点で静的に評価されて条件判断ではなくなるのはわかるのですが...。 ということで、C ならば for(;;) 派です :-) 短く書くなら本体一行で。 int gcd(int a, int b) { return (a%=b)?gcd(b,a):b; }
実用で書くなら初段に引数の正整数チェック入れますので1行じゃ書きません。 私のコードもIsamiさんのコードもbに0を入れた時点で :-) というのはともかく計算量の評価は必要、というのには同意します。 ということで、問題なのですが、int が 64 bit 符号なし整数のときに繰り返し回数(再帰段数)の最大値を評価しなさい :-)
どこまで短く出来るかだけにこだわってるだけだから、実用性は無視でよろしいかとw で冷静に考えれば a = a % b を計算した後は必ず a<bなのだから続けて b = b % a を計算しちゃえばいいですね。そういう意味でa>bの大小を比較するのは無意味で、最初の一回目の計算が無駄になるかならないかくらいのデメリットしかない。 参考までにループ回数はもちろん入力数によりけりですが、ログスケール。なので32bit同士くらいなら、一瞬。 でかい数、例えば、 3^1000+1と 4^1000+1の最大公約数を求めるとしても135回です。
最大数の証明 初期値a0, b0に関して、 a0 > b0 とします。 a1 = a0 % b0 (a1 < b0 < a0) この演算後a0はどの程度小さくなるかを考えます。 a0 = b0/2のときはアルゴリズムは終了。 a0 < b0/2とすれば明らかに a1 < a0/2 a1 > b0/2とすれば a1 = a0 % b0 = (a0 - b0) < a0/2 いずれにしろ a1はa0の半分以下になります。つまり64bit intなら最悪でも64回で終了です。
上記より最悪の場合を構成するには、アルゴリズムを逆に適用して初期値 a(0) = 1, a(1) = 1 より a(k) = a(k-2) + a(k-1) を順次計算してやればいいのかな。(フィボナッチ数ですね) これによれば、符号なし64bit intでワーストケースは a = 7540113804746346429 b = 12200160415121876738 で90回前後の再帰で計算可能です。(境界条件のとこで数えるの面倒なので前後としときます:-)) a%=bとb%=aを一回のループとして45回くらい。