해결된 질문
작성
·
74
0
몇 챕터/몇 강을 수강 중이신가요?
1-11
어떤 알고리즘을 학습하고 계신가요?
소수 나열하기
여기까지 이해하신 내용은 무엇인가요?
어느 부분에서 막히셨나요?
소수 나열하기 2차 개선 조건식 위치
input = 20
def find_prime_list_under_number(number):
prime_list = []
for n in range(2, number + 1):
for i in prime_list:
if n % i == 0 and i * i <= n:
break
else:
prime_list.append(n)
return prime_list
result = find_prime_list_under_number(input)
print(result)
코드의 어떤 로직이 이해가 안 되시나요?
if n % i == 0 and i * i <= n: # 강의 노트
if i * i <= n and n % i == 0: # 수업
어떤 개념이 헷갈리시나요?
강의 노트와 수업에서의 개선된 로직이 어떤 연산을 줄여서 시간복잡도가 개선되는 건가요?
i가 n의 제곱근보다 클 경우 나머지 연산을 수행할 필요가 없어 불필요한 나머지 연산을 수행하지 않기 위해 제곱근에 대한 조건식을 먼저 검사하지 않아도 되는건가요?
문제 해결을 위해 어떤 시도를 해보셨나요?
에러가 발생했다면 어떤 에러인가요?
현재 작성하신 코드를 공유해주세요
input = 20
def find_prime_list_under_number(number):
prime_list = []
for n in range(2, number + 1):
is_prime = True
for i in prime_list:
if i * i > n:
break
if n % i == 0:
is_prime = False
break
if is_prime:
prime_list.append(n)
return prime_list
result = find_prime_list_under_number(input)
print(result)
답변 2
0
안녕하세요 인프런님! 헉 닉네임이 인프런일수도 있군요
우선 좋은 질문 감사합니다!!
질문해주신 내용에 대해서 답변드리면, 말씀해주신 내용이 맞습니다!
그 두 가지 조건식의 차이점은 조건 순서의 차이입니다. 논리적으로는 완전히 동일하지만, 실행 효율성 측면에서는 차이가 있습니다. 파이썬에서 and
연산자는 단락 평가(short-circuit evaluation) 방식을 사용합니다. 즉, 첫 번째 조건이 False
라면 두 번째 조건은 아예 평가하지 않습니다.
즉, 다음과 같은 코드에서 다음 순서로 동작합니다 if i * i <= n and n % i == 0
먼저 i * i <= n
조건을 확인합니다.
이 조건이 False
라면(즉, i
가 n
의 제곱근보다 크다면), 나머지 조건(n % i == 0
)은 확인하지 않고 넘어갑니다.
이것이 성능 향상을 불러오는 이용은 다음과 같습니다.
나머지 연산(%
)은 계산 비용이 비교적 높습니다:
나머지 연산은 나눗셈을 포함하기 때문에 단순 비교보다 CPU 사이클을 더 많이 소모합니다.
제곱근 이상의 소수로는 확인할 필요가 없습니다:
수학적으로, 어떤 수 n
이 합성수라면 반드시 √n
이하의 소수로 나누어 떨어집니다.
예: 16은 2로 나누어 떨어지므로, 8(16÷2)로 나누어 떨어지는지 확인할 필요가 없습니다.
불필요한 연산 회피:
i * i > n
이라면, 그 이후의 모든 i
에 대해서도 나머지 연산을 할 필요가 없습니다.
따라서 단락 평가 때문에 나머지 연산의 횟수를 줄여 성능을 향상시킨다고 봐주시면 좋을 것 같습니다! 언제든 또 질문주시고 좋은 하루 되시길 바랍니다!!
안녕하세요 인프런님!! 우선 확인이 늦어 죄송합니다 ;_; 추가 질문에 대해서 알림이 안오는 구조라서 지금에서야 봤습니다!
교재 이상
엇 그렇네요!!! 교재 부분 변경해뒀습니다 확인 너무너무 감사드립니다!!!!
break 문 추가 제안
결론부터 말씀드리면, 말씀하신 것처럼 질문자님이 작성하신 코드 방식이 더 효율적인게 맞습니다!! 특히 i * i > n
조건을 먼저 확인하고 바로 반복문을 탈출하는 방식이 시간 복잡도 측면에서 더 나은 구조로 판단됩니다!!
기존 코드에서처럼 n % i == 0 and i * i <= n
순서로 조건을 작성하면, n % i == 0
이라는 나머지 연산을 먼저 수행하게 됩니다. 하지만 나머지 연산은 비교적 연산 비용이 높은 편이기 때문에, 먼저 i * i > n
을 판단하고 루프를 종료하는 것이 더 효율적입니다!!
또한 질문자님이 지적하신 대로, 어떤 수 n
이 소수인지 판단할 때 i * i > n
이 되는 시점 이후에는 더 이상 어떤 연산도 수행할 필요가 없습니다. 그런데 기존 코드에서는 n % i == 0
이 먼저 평가되기 때문에, 조건에 따라 불필요하게 그 이후 i * i
를 계속 계산하거나 다음 i
까지도 반복문이 진행될 수 있습니다.
즉, 말씀하신 내용이 맞고, 제가 그 부분을 충분히 고려하지 못했던 것 같습니다.
불필요한 연산을 더 줄일 수 있다는 점에서 제안해주신 방식이 더 효율적이네요.
말씀해주신 방향으로 코드 개선도 고려해보겠습니다!!! 문제의 본질을 정확히 이해하고 성능까지 고려해 개선 방향을 제시하신 점이 인상 깊었습니다. 이런 접근은 이후 다른 알고리즘 문제를 푸실 때도 큰 도움이 될 것 같습니다!! 좋은 질문 너무너무 감사합니다!!! ㅎㅎㅎ
0
안녕하세요, 인프런 AI 인턴입니다.
소수 나열하기 문제에서 두 가지 코드 작성 방법이 혼동되셨군요. 두 코드의 차이는 조건식의 위치이고, 이는 불필요한 연산을 줄여주어 시간 복잡도 개선에 영향을 미칩니다.
문제의 본질: 소수를 찾기 위해선, 대상 수 n
이 소수인지 판별해야 합니다. 이때, 2부터 시작해서 이미 확인된 소수로만 나누어 떨어지지 않으면 n
은 소수입니다.
조건문의 순서:
if n % i == 0 and i * i <= n
(강의 노트): 이 코드에서는 나누기 연산이 먼저 수행됩니다. i * i <= n
조건이 거짓이면 필요없는 나누기 연산까지 하고 조건문에서 빠져나옵니다.if i * i <= n and n % i == 0
(수업): 이 코드에서는 나누기 연산 전에 제곱근 제한 조건을 먼저 검사하여, 제곱근 조건을 넘는 시점에서 나누기 연산조차 하지 않음으로써 불필요한 연산을 줄이는 이점이 있습니다.제곱근을 이용한 소수 판별: 숫자 n
의 소수 여부를 판단할 때 소수를 i
로 나눌 필요는 i * i <= n
일 때까지입니다. 즉, i
가 커지면서 i * i
가 n
보다 큰 순간부터는 더 이상 나누어볼 필요가 없습니다.
효율성의 차이: if i * i <= n and n % i == 0
는 주 연산이 줄어들어서 성능이 조금 더 향상됩니다.
위 내용을 바탕으로 두 조건 모두 사용 가능하나, 최적의 성능을 위해서는 if i * i <= n
체크를 먼저 사용하는 것이 좋습니다.
관련하여 자세한 예제 설명은 아래 링크를 참조하시면 좋습니다:
- “에라토스테네스의 체를 이용한 소수 찾기 - Markdown”
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
답변 감사합니다.
단락 평가 방식으로 인해 계산 비용이 적은 조건을 앞에 위치시켜야 하는 것은 이해했습니다. 현재 강의 노트에 나와있는 조건은 계산 비용이 비교적 높은 나머지 연산이 앞에 위치해 있으므로 수정이 필요해보입니다.
추가적으로 한가지 더 질문드립니다.
불필요한 연산을 회피하기 위해
i * i > n
이라면, 그 이후의 모든i
에 대해서도 나머지 연산을 할 필요가 없다는 것은 이해했지만, 그 이후의 모든i
에 대한 나머지 연산 뿐만 아니라 첫번째 조건 연산(i * i > n
)도 하지 않도록 코드 변경이 필요하지 않을까요?현재 딩코딩코님이 제안해주신 코드는 두 조건을 만족하는 경우에만
break
로for
문을 탈출하기 때문에prime_list
에있는 모든i
에 대해서i * i <= n
조건을 수행해야 합니다.예를 들어 7이 소수인지 확인하기 위해
i = 3
이후의i * i <= n
조건을 더이상 수행할 필요가 없지만 현재 딩코딩코님이 제안해주신 코드에서는i = 3
인 경우n % i == 0
조건을 만족하지 못하기 때문에break
문으로for
문을 탈출하지 않아i = 5
인 경우의i * i <= n
조건을 검사해야 합니다.따라서 저는 아래와 같이 코드를 작성해야한다고 생각하는데 어떻게 생각하시나요?