에라토스테네스의 체
수학에서 소수를 찾는 방법론 중 하나입니다.
알고리즘
- 2부터 소수를 구하고자 하는 구간의 모든 수를 나열한다.
- 자기 자신을 제외한 2의 배수를 모두 지운다.
- 제외되지 않은 3은 소수이다.
- 자기 자신을 제외한 3의 배수를 모두 지운다.
- 제외되지 않은 5는 소수이다.
- 자기 자신을 제외한 5의 배수를 모두 지운다.
- 제외되지 않은 7은 소수이다.
- 자기 자신을 제외한 7의 배수를 모두 지운다.
위의 과정을 반복하면 구하는 구간의 모든 소수가 남는다.
만약 120까지 수 중에서 소수를 구하고 싶다면, 11^2 > 120 이므로 11보다 작은 수들의 배수들만 지워도 소수를 구할 수 있습니다.
Python 코드
소수 리스트 구하기
에라토스테네스의 체를 이용하여 120이하의 소수 리스트를 구해보겠습니다.
이렇게 입력한 n 이하의 소수 리스트를 구할 수 있습니다.
만일 단일 n이 소수인지 판별하고 싶다면 해당 소수 리스트에서 sqrt(n) 이하의 소수로 나누었을 때 나누어지는 수가 없는지 확인하여 판별할 수 있습니다.
단일 소수 판별
간단하게 n만 소수인지 확인하고 싶다면 2이상 sqrt(n)이하의 수들로 n을 나누어보고 나누어지는 수가 없는지 확인하면 됩니다.
연속된 큰 수의 소수판별
n이 엄청나게 큰데다 연속해서 판별해야 한다면, 에라토스테네스의 체를 활용하여 sqrt(n) 이하의 소수 리스트를 구한 다음 활용하는 것이 더 빠를 수 있습니다.
아래는 소수 1141097을 판별하는 시간을 비교해 본 코드입니다.
def is_prime1(n):
for num in range(2, int(n**1/2) + 1):
if n % num == 0:
return False
return True
def prime_list(n):
lst = [0] * n
m = int(n ** 0.5)
for i in range(2, m + 1):
if lst[i] == 0:
for j in range(i+i, n, i):
lst[j] = 1
return [i for i in range(2, n) if lst[i] == 0]
def is_prime2(n):
lst = prime_list(n)
for num in lst:
if n % num == 0:
return False
return True
is_prime1(1141097)
is_prime2(1141097)
1. is_prime1(n)을 활용하여 계산 할 경우 약 0.15초
2. is_prime2(n)을 활용하여 계산 할 경우 약 0.9 초, 이 중 0.88초는 prime_list(n)에서 소요
단일 소수판별은 is_prime1이 빠르지만 11401097, 1141093, 1141087 등과 같이 큰 소수를 10번이나 계산한다면
is_prime1은 0.15 * 10으로 약 1.5초가 됩니다.
만약 is_prime2를 prime_list(n)와 따로 계산하여 리스트를 먼저 구한다면 0.88 + 0.02 * 10으로 약 1초로 더 빠르게 됩니다.
더 많은 소수를 판별한다면 차이는 더 벌어지므로 큰 수를 여러번 판별해야 할 경우 에라토스테네스의 체를 활용하여 소수 리스트를 미리 구하는 것이 효율적입니다.
'Algorithm > Algorithm' 카테고리의 다른 글
[Python] 세그먼트 트리, Segment Tree 구조 이해 (파이썬 코드) (0) | 2024.10.17 |
---|---|
[Python] 너비 우선 탐색, BFS (Breadth First Search) 알고리즘 파이썬 코드 (0) | 2024.10.10 |
[Python] 깊이 우선 탐색, DFS (Depth First Search) 알고리즘 파이썬 코드 (1) | 2024.10.10 |
[Python] 유클리드 호제법 (최대공약수 구하기) (0) | 2023.01.30 |
최소 스패닝 트리(MST, Minimum Spanning Tree), Kruskal & Prim 알고리즘 (0) | 2023.01.12 |