유클리드 호제법
최근 수정 시각: (5년 전)
호제법에서 넘어옴
1. 개요 [편집]
Euclidean Algorithm · —互除法
두 양의 정수, 혹은 두 다항식의 최대공약수를 구하는 방법으로, 한국의 수학 교육과정에서는 다루지 않는다(자세하게 다루지는 않지만, 2015 개정 교육과정 중학교 1학년 수학 교과서에 짤막하게 나온다).[1] 일본의 수학 교육과정에서는 수학A로 다룬다. 하지만 여타 다른 교육과정 외 내용들이 그렇듯이 알아놓으면 몇몇 문제를 푸는데 굉장히 유용하다. 알려주지는 않으면서 문제는 낸다. 호제법(互除法)이라는 말은 서로(互) 나누기(除) 때문에 붙여진 이름이다. 이 뜻의 '호제' 라는 단어가 따로 있지는 않다. 이 알고리즘은 유클리드의 원론에 적혀있는 내용으로, 인류 최초의 알고리즘이라 한다. 알고리즘의 골자는 다음과 같다.
두 양의 정수, 혹은 두 다항식의 최대공약수를 구하는 방법으로, 한국의 수학 교육과정에서는 다루지 않는다(자세하게 다루지는 않지만, 2015 개정 교육과정 중학교 1학년 수학 교과서에 짤막하게 나온다).[1] 일본의 수학 교육과정에서는 수학A로 다룬다. 하지만 여타 다른 교육과정 외 내용들이 그렇듯이 알아놓으면 몇몇 문제를 푸는데 굉장히 유용하다.
2. 증명 [편집]
3. 활용 [편집]
3.1. 최대공약수 [편집]
개요에도 쓰여있듯이, 이 알고리즘은 두 수의 최대공약수를 구할 때 쓸 수 있다. 한 예로 12345와 1234의 최대공약수를 구하고 싶다 하자. 위 알고리즘에 두 수를 대입하면,
따라서 두 수의 최대공약수는 임을 알 수 있다.
따라서 두 수의 최대공약수는 임을 알 수 있다.
3.2. 연분수 [편집]
3.3. 소스 코드 [편집]
int Gcd(int a, int b)
{
int r = a % b;
if (r == 0)
return b;
else
return Gcd(b, r);
}
손으로 계산할 때는 제수와 피제수의 값 크기를 비교해서 적절하게 배열하지만 수식이나 코드로 나타낼 때는 신경쓰지 않아도 되는데, a<b일 때 a mod b ≡ a(a%b==a)이므로 Gcd(a,b)는 Gcd(b,a)를 호출한다. 즉 재귀 과정에서 자연스럽게 큰 값이 a로, 작은 값이 b로 들어간다.
3.3.1. C [편집]
int Euclidean(int a, int b)
{
return a%b ? Euclidean(b, a%b) : b;
}
가장 짧은 코드
f(a,b){return b?f(b,a%b):a;}
3.3.2. Python [편집]
3.3.2.1. 반복문 [편집]
def Euclidean(a, b):
while b != 0:
r = a % b
a = b
b = r
return a
3.3.2.2. 재귀문 [편집]
def Euclidean(a, b):
r = b % a
if r == 0:
return a
else:
return Euclidean(r, a)
3.4. 알고리즘으로서의 성능 [편집]
두 수 를 나눈 나머지가 이라면 황금비 에 대해 이거나 둘 중 하나가 성립한다. (만약 이면 이기 때문) 이를 이용하면 수학적 귀납법으로 "에 대해 호제법을 수행하면 나눗셈 횟수는 이하이다"를 보일 수 있다. 피보나치 수열의 이웃한 두 항의 경우 정확히 저 횟수만큼 나눗셈을 하게 되므로 실질적인 최소값이라 할 수 있다. 더 나아가면 주어진 에 대해 나눗셈 횟수가 최대가 되는 는 혹은 로 주어진다는 것을 보일 수 있지만 아주 중요한 것은 아니다.
어쨌든 나눗셈 횟수는 이 된다. 정수 나눗셈 1회의 복잡도가 제수와 몫의 자리수 개수에 비례한다는, 즉 로 나타난다는 것까지 고려하면 (자세한 과정은 생략하겠지만) 유클리드 호제법 전체의 시간 복잡도가 로 나타남도 보일 수 있다. 정수의 입력 자체에서 를 쓰는 것을 감안하면 꽤 좋은 효율이다.
하지만 유클리드 호제법도 최적의 알고리즘은 아니고(!!), 정말 큰 수의 경우에는 이 보장되는 다른 준선형적 알고리즘들을 사용한다. 다행히도 2만 자리 넘어가는 정말 큰 수가 아닌 이상에야 호제법 정도면 크게 퍼포먼스가 떨어지진 않는다.
공간 복잡도 면에서는 위에 코드를 보면 알겠지만 변수 3개로도 충분하다. 다만 재귀를 쓰면 나눗셈 횟수만큼 호출 스택에서 을 잡아먹으므로 쓰지 말자. 를 찾는 확장된 유클리드 알고리즘에서도 나눗셈 과정을 트랙할 필요는 없고, 코드를 잘 짜면 변수 4개로 처리할 수 있다.
어쨌든 나눗셈 횟수는 이 된다. 정수 나눗셈 1회의 복잡도가 제수와 몫의 자리수 개수에 비례한다는, 즉 로 나타난다는 것까지 고려하면 (자세한 과정은 생략하겠지만) 유클리드 호제법 전체의 시간 복잡도가 로 나타남도 보일 수 있다. 정수의 입력 자체에서 를 쓰는 것을 감안하면 꽤 좋은 효율이다.
하지만 유클리드 호제법도 최적의 알고리즘은 아니고(!!), 정말 큰 수의 경우에는 이 보장되는 다른 준선형적 알고리즘들을 사용한다. 다행히도 2만 자리 넘어가는 정말 큰 수가 아닌 이상에야 호제법 정도면 크게 퍼포먼스가 떨어지진 않는다.
공간 복잡도 면에서는 위에 코드를 보면 알겠지만 변수 3개로도 충분하다. 다만 재귀를 쓰면 나눗셈 횟수만큼 호출 스택에서 을 잡아먹으므로 쓰지 말자. 를 찾는 확장된 유클리드 알고리즘에서도 나눗셈 과정을 트랙할 필요는 없고, 코드를 잘 짜면 변수 4개로 처리할 수 있다.
4. 다항식에서의 호제법 [편집]
두 다항식 에 관하여, 이고 이라 하면, 이 성립한다.
증명 방법 역시 정수의 경우와 동일하므로 생략한다. 단, 이 호제법이 성립하는 것은, 어디까지나 유클리드 정역의 환 위에서만이다.
4.1. 예시 [편집]
5. 유한체에서 [편집]
6. 관련 문서 [편집]
라이선스를 별도로 명시하지 않은 문서는 CC BY-NC-SA 2.0 KR에 따라 이용할 수 있습니다.
기여하신 문서의 저작권은 각 기여자에게 있으며, 각 기여자는 기여하신 부분의 저작권을 갖습니다.
문서의 기여자는 역사 탭에서 확인할 수 있습니다.
접두어의 N: - 나무위키 사용자, R: - 리그베다 위키의 사용자를 뜻합니다.
자세한 사항은 나무위키에서 동일한 문서의 역사를 참고하시기 바랍니다.