대학혁신지원사업		[혁신113]
	대학혁신지원사업
	SW비교과프로그램 결과 보고서

					제 출 번 호		작성하지 마세요
멘토	이름		멘티	이름
	학과(부)			학과(부)
	학번			학번
	학년			학년
	이메일			이메일
활동 일시		2020.??.?? 00:00 ~ 2020.??.?? 00:00 (분 단위로 작성, 또는 1시간 몇분 형태로)
코드 리뷰 클리닉 방법 (수행 방법을 체크(☑) 하세요)
☐ Visual Studio 툴의 LiveShare 기능을 이용			☐ MicroSoft 사의 Teams 툴을 이용
☐ (무료 버전) TeamViewer 툴을 이용			☐ 기타 ( )

코드 리뷰 클리닉 수행 전

■ 코드 리뷰 신청 내용

- 소수 구하는 코드 개선

- 반복문(while) 개선 방법

- 기타 피드백 요청

코드 리뷰 클리닉 수행 후

■ 코드 리뷰 클리닉 수행 내용 ■

1. global 선언의 존재 유무

(1번은 문제점은 없으나, 1학년 후배이니 공부 차원에서 제시합니다.)

Java와 같은 언어에서는 변수를 선언할 때 해당 변수가 지역 또는 전역 변수인지를 구분해 주는 접근 지정자가 필요하다. 그렇지 않으면 불가피하게 이름이 겹치는 변수가 존재할 경우 이를 구분하지 못하는 상황이 생긴다. 다만, 리눅스에서는 이 접근 지정자가 별도로 필요하지 않다는 것이 특징이기도 하지만 생략을 했다는 만큼 이런 요소를 사용하는 것은 신중하게 접근할 필요가 있다.

우선, global은 전역 변수를 선언하는 것이 맞지만 변수를 외부에서 선언한다는 것 자체가 기본적으로 전역 변수임을 선언하는 것과 동일하기 때문에 global를 쓰는 이유가 없다. 이를 생략하고도 본 코드는 변수들이 최초 호출 시점부터 실행 자체에는 문제가 없기 때문이다.

Global의 사용은 변수 선언 시, ‘해당 변수가 지역 변수 취급을 받는 상황에서 전역 변수임을 별도로 명시’하는 용도 정도가 되겠다. 만약, 메소드 안에서 선언되는 변수들은 전부 지역 변수 취급을 받기 때문에 외부에서는 사용할 수가 없다.

예를 들어, 아래의 왼쪽과 같은 코드는 실행할 경우 에러가 난다. 메소드를 호출했으니 내부의 코드는 돌아가겠지만 변수 a는 메소드 내의 지역 변수이기 때문이다.

하지만, 오른쪽과 같이 지역 변수에 해당되는 a를 메소드 내부에서 global 을 붙여 선언하고, 메소드 외부의  print(a)를 호출하면 정상적으로 호출이 가능하다.

2. 알고리즘의 간략화

멘티 학생이 제시한 현재의 코드는 2중 반복문의 구성으로 되어있으며 for문 안에 while문이 존재하고, while문은 조건에 맞는 상황이 될 경우 break를 통해 빠져나오게 된다.

현재는 for문에서 전체 범위를 결정하고, while문을 통해서 소수를 찾을 때 까지 연산을 하는 과정을 거치고 있다.

100 정도 범위의 수의 경우에는 모르지만 10,000 정도의 수만 되어도 3.5초 정도가 걸린다. 모든 경우의 수를 전부 대입해 계산하기 때문이므로 이를 간략화 시킬 필요가 있다.

① 1차 개선

현재는 리스트에다가 소수로 판별된 결과를 삽입하는데, 성능에 영향을 줄 요인일 수 있으므로 즉각 결과를 내놓도록 개선하고자 한다.

소수의 정의를 간단하게 생각해보면

- 1은 소수가 아님

- 2부터 N-1까지의 자연수 중에서 순서대로 N을 나눴을 경우 나누어 떨어지는 수가 하나라도 없다면 소수

이 두 요소를 조합해 기본적인 코드를 만들면 다음과 같다.

상기 코드는 10,000까지 계산한 경과 시간만 해도 0.36초라는 좋은 성능을 보여주었다. while 문으로 일일이 대입하지 않고, 결과를 list로 내기 위해 관련 내용을 쓰지 않아도 성능을 개선할 수 있다. 하지만, 더 큰 수의 결과에서는 성능의 체감 폭이 확 줄일 수가 있는데, 조건을 더 붙어서 개선을 해보고자 한다.

② 2차 개선

성능 개선의 핵심은 ‘코드 실행의 대상을 줄이는 것’이다. 사전에 소수의 대상일 수가 없는 수를 배제하는 것으로 연산량을 줄여 성능을 끌어올리려는 것이다.

- 2를 제외한 모든 짝수는 3개의 이상의 약수를 가지고 있다. (★)

이 조건만으로 소수가 아니므로 저 조건을 제외해보기로 한다.

10,000을 기준으로 0.1초가 감소한 0.26초가 되었다. 몇가지 조건을 더 붙일 수도 있다. 어떤 자연수가 하나 있으면 a라는 수로 나누어 질 때 a * b = N 라는 식이 성립하며, 이 식이 성립하는 의미는 N은 a뿐만 아니라 b로도 나눠짐을 의미한다.

③ 3차 개선

N의 제곱근인 r을 기준으로 곱해서 N이 될 수 있는 약수들이 같은 개수로 분포하는데, 이를 통해 추가할 수 있는 조건은

- N이 소수인지 확인하려면 N의 제곱근까지만 검사

이를 코드로 반영해본다.

10,000을 기준으로 0.05초가 걸리며, 5분의 1이나 개선된 모습을 보여주었다. 이와 같이 방법은 다양하며, 불필요한 연산을 최대한 배제하는 것이 좋은 코드의 핵심이고 그만큼 좋은 결과를 보여준다.

■ 번외 – 에라토스테네스의 체

위와 같이 소수를 구하는데 있어서 연산량을 줄일 수 있는 방법 중 하나다. 그가 제안한 방법은 정해진 범위 내의 수에서 합성수(약수가 3개 이상인 자연수)를 지우는 방식으로 소수를 찾는 법이다.

- 1을 제거

- 지워지지 않은 범위 내에 수에서 제일 작은 2를 소수로 채택하고 나머지 2의 배수를 삭제

- 지워지지 않은 범위 내에 수에서 제일 작은 3을 소수로 채택하고, 3의 배수를 모두 지운다.

- 지워지지 않은 수 중에서 제일 작은 5를 소수로 채택하고 나머지 5의 배수를 지운다.

- 이런 방법으로 나오는 제일 작은 수를 계속해서 소수로 채택해 범위 내의 해당 수의 배수를 지운다.

1부터 100까지의 표에서 합성수를 지워 찾은 결과를 사진으로 나타낸 것이다.

이를 코드의 형태로 나타내면 다음과 같다.

10,000을 기준으로 계산 시간은 0.035초 정도이며, 3차 개선 코드보다도 더 빠른 결과를 보여준다.

위와 같이 코드 리뷰 클리닉 현황 및 보고서를 제출합니다.

2020. 09.   .

• 신청자(멘토):                  (인)

• 지 도 교 수:                  (인)

• 담당자(사업단):                  (인)

대학교육혁신단장 귀하