ユークリッドの互除法とは、2つの自然数の最大公約数を求めるアルゴリズムである。
最大公約数を求めたい2つの整数を m、n (どちらか一方が0以上の整数、もう一方が正の整数)とすると、以下のような手順で、m と n の最大公約数を求めることが出来る。
剰余の代わりに減算を用いる方法もあるが、両者の間に本質的な差異は何も無い。
ユークリッドの互除法は最古のアルゴリズムとしても有名だが、優れたアルゴリズムと言われる所以は手数の少なさにある。アルゴリズムを終了するのに十分な手数は、n の桁数に比例するのである。具体的に言うと、n の10進桁数の5倍だけ行うまでに、結果がわかる。紀元前の時代にここまで優れたアルゴリズムが存在したことは注目に値する。
| m | n | r | |
|---|---|---|---|
| (1) | 728 | 693 | 35 |
| (2) | 693 | 35 | 28 |
| (3) | 35 | 28 | 7 |
| (4) | 28 | 7 | 0 |
| (5) | 7 | 0 | - |
なお、m < n のとき、m ÷ n → 0 余り m であるため、m、n の大小関係に関して特に制約は無い。
ここではPythonでの実装例を記載する。他のプログラミング言語においても、ループ処理、再帰処理等が実装可能であれば大体同じようにして実装出来る。なお、引数 m、n については前提条件(どちらか一方が0以上の整数、もう一方が正の整数)を必ず満たしているものとする。
def getGCD(m, n):
while n != 0:
m, n = n, m % n
return m
def getGCD(m, n):
if n == 0:
return m
else:
return getGCD(n, m % n)
def getGCD(m, n):
return m if n == 0 else getGCD(n, m % n)
a,bの最大公約数をdとして、ユークリッドの互除法の逆をたどることでax+by=dとなる整数x,yを全て求めることができる。これはa,bが互いに素、つまりd=1である時に特に有用。
a=728、b=693とする。
728=693+35
693=35×19+28
35=28+7
28=7×4+0
最大公約数が7と分かったので逆をたどる。
7=35-28
=35-(693-35×19)=35×20-693
=(728-693)×20-693=728×20-693×21
以上より、x=20、y=-21が候補の一つ。
728x+693y=7なので、728x-728×20+693y-693×(-21)=0
104,99は互いに素なので、kを整数として、x-20は99k、y+21は104k。
以上より、x=99k+20、y=104k-21の形で表される。
多項式に関しても整数と同じように最大公約多項式や最小公倍多項式といったものが定義できる。
例 2x9-x8-2x+1 と x4+x3-x-1 の最大公約多項式を実数係数の範囲で求める。
(2x9-x8-2x-1)=(x4+x3-x-1)(2x5-3x4+3x3-x2)+(2x3-x2-2x+1)
(x4+x3-x-1)=(2x3-x2-2x+1)(x/2+3/4)+7/4(x2-1)
(2x3-x2-2x+1)=7/4(x2-1)(8x/7-4/7)+0=(x2-1)(2x-1)+0
最大公約多項式は(x2-1)=(x+1)(x-1)と分かった。
実際、2x9-x8-2x+1=(x4+1)(x2+1)(2x-1)(x+1)(x-1)、x4+x3-x-1=(x+1)(x-1)(x2+x+1)であることから確認できる。
先ほどの表と対応させると以下のようになる。
| m | n | r | |
|---|---|---|---|
| (1) | 2x9-x8-2x+1 | x4+x3-x-1 | 2x3-x2-2x+1 |
| (2) | x4+x3-x-1 | 2x3-x2-2x+1 | x2-1 |
| (3) | 2x3-x2-2x+1 | x2-1 | 0 |
| (4) | x2-1 | 0 | - |
一般に、ユークリッド整域と呼ばれる集合であればユークリッドの互除法が使える。整数の集合と1変数の多項式の集合は共にユークリッド整域の構造を持つ。しかし、2変数以上の多項式はユークリッド整域ではないのでユークリッドの互除法を適用する事ができない。直接因数分解するより余計めんどくさいが1変数多項式に互除法を適用できるという事実が重要なのである。用語の詳しい説明は環(数学)を参照。
こちらも拡張ユークリッドの互除法が使えるが、係数が多く非常にめんどくさいことになる。
掲示板
9 ななしのよっしん
2016/11/10(木) 00:30:48 ID: jvIkoIKVD4
>>8
最初の一回だけ必要なんだよな。
(前提として、最初に与えられる値が a ≧ b としてるから)
まあ、実際に実装する場合はラッパー関数で最初だけ大小比較するんだろうが。
10 ななしのよっしん
2017/10/03(火) 21:14:19 ID: zMqL4A08ZL
>>9
その前提、本当に必要?
記事の例を逆さにして、「693と728の最大公約数」を求めてみよう。
0. 693 ÷ 728 → 0 あまり 693
1. 728 ÷ 693 → 1 あまり 35
2. 693 ÷ 35 → 19 あまり 28
3. 35 ÷ 28 → 1 あまり 7
4. 28 ÷ 7 → 4 あまり 0
よって、693と728の最大公約数は7。
大小比較によって手順を1回だけ減らせはするけど、果たしてコードが増える苦労に見合うか…
11 ななしのよっしん
2019/10/12(土) 19:57:42 ID: R5MLGVvsQz
互除法の拡張(改造物)っていろいろあるけど
この記事の拡張ユークリッド互除法は「互除法の逆行」という名前で呼んでいるpdfがあってなかなかよかった
台風ひまひま
急上昇ワード改
最終更新:2025/12/10(水) 04:00
最終更新:2025/12/10(水) 04:00
ウォッチリストに追加しました!
すでにウォッチリストに
入っています。
追加に失敗しました。
ほめた!
ほめるを取消しました。
ほめるに失敗しました。
ほめるの取消しに失敗しました。