프로젝트 오일러 문제들을 풀다보니 소수에 관련된 문제가 많이 나왔다.
처음 소수 구하는 알고리즘을 생각할 당시, 관련 지식이 미비해(공부한 지 너무 오래돼서) 구현한 알고리즘이 너무 조잡했다. (속도가 너무 느렸다.)
오늘 다시 차근차근 검색해 가며 다시 짜봤다.
가장 기초적인 방법
1은 소수가 아니다.
2부터 자신의 수 이전까지 나눠서 떨어진다면 소수가 아니다. (소수는 1과 자신 외에 나눠지면 안된다.)
예 ) 15가 소수인지 판단하려면
15를 2로 나눠 나머지가 0인지 판단. 아니면 15를 3으로 나눠 나머지가 0인지 판단..소수가 아님
씩으로 판별을 하다보니 큰 숫자 (600851475143)가 나온다면 엄청난 계산을 해야 했다.
def is_prime(number):
if number == 1:
return False
for i in range(2, number):
if number % i == 0:
return False
return True
나눌 때 절반 까지만 나눔
절반 이상의 숫자들은 확인할 필요가 없는 숫자이기 때문이다.
예를 들어 80이라는 숫자가 있다면, 자기자신을 제외하고 절반을 초과하는 숫자로 나눴을 때 나머지가 0이 되는 숫자가 나올 수가 없기 때문이다.
def is_prime2(number):
if number < 2:
return False
if number == 2:
return True
if number % 2 == 0:
return False
for i in range(3, (number // 2) + 1):
if number % i == 0:
return False
return True
루트까지만 확인
약수의 중심을 구하는 방법이다.
예를 들어 80이라는 숫자가 있다면, 약수들이 1, 2, 4, 5, 8, 10, 16, 20, 40, 80 이 된다.
이것은 1 x 80, 2 x 40, 4 x 20, 5 x 16, 8 x 10, 10 x 8, 16 x 5, 20 x 4, 40 x 2, 80 x 1이 되는 것이다.
이것을 보면 8 이후의 약수들은 8까지의 약수들의 역순(반비례)이다. 이는 80의 제곱근과 엇비슷하다. (80의 제곱근 8.94..........)
따라서 그 이후의 숫자들은 판별할 필요가 없다.
def is_prime3(number):
if number < 2:
return False
if number == 2:
return True
if number % 2 == 0:
return False
for i in range(3, int(number ** 0.5) + 1):
if number % i == 0:
return False
return True
참고사이트
'프로그래밍 > 알고리즘' 카테고리의 다른 글
10001번째의 소수 (0) | 2021.01.27 |
---|---|
1부터 100까지 "제곱의 합"과 "합의 제곱"의 차는? (0) | 2021.01.26 |
1 ~ 20 사이의 어떤 수로도 나누어 떨어지는 가장 작은 수 (0) | 2021.01.25 |
세자리 수를 곱해 만들 수 있는 가장 큰 대칭수 (0) | 2021.01.24 |
가장 큰 소인수 구하기 (0) | 2021.01.23 |