다음 소스 코드는 http://www.daniweb.com/code/snippet808.html 에서 볼 수 있는 (주어진 범위 안에서) 소수(prime number, 북한 용어로는 씨수) 찾기 C++ 소스 코드이다.
- # include<iostream.h>
- # include<math.h>
- void main()
- {
- int flag=0;
- unsigned long l, h, temp;
- cout<<"Enter the lower limit:"; cin>>l;
- cout<<"Enter the higher limit:"; cin>>h;
- if(l%2==0)
- {
- if(l==2) cout<<"2\t";
- l++; //taking only odd no
- }
- for(;l<=h;l+=2, flag=0)
- {
- temp=sqrt(l);
- if(temp%2==0) temp++; //taking only odd no
- for(; temp>2; temp--)
- {
- if(l%temp==0)
- {
- flag=1;
- break;
- }
- }
- if(flag==0) cout<<l<<"\t";
- }
- }
우선 위의 코드를 파이썬 소스 코드 처럼 들여쓰기 규칙을 엄격히 적용하여 아래 처럼 재작성하였다.
- #include <iostream.h>
- # include <math.h>
- void main() {
- int flag = 0;
- unsigned long l, h, temp;
- cout << "Enter the lower limit: ";
- cin >> l;
- cout << "Enter the upper limit: ";
- cin >> h;
- if (l % 2 == 0) {
- if (l == 2)
- cout << "2\t";
- l++; // Taking only odd numbers.
- }
- for (; l <= h; l += 2, flag = 0) {
- temp = sqrt(l);
- if (temp % 2 == 0)
- temp++; // Taking only odd numbers.
- for (; temp > 2; temp--) {
- if (l % temp == 0) {
- flag = 1;
- break;
- }
- }
- if (flag == 0)
- cout << l << "\t";
- }
- }
하지만 아직 표준 C++에 맞지 않으므로 더 고쳐 보았다.
- #include <iostream>
- #include <cmath>
- using namespace std;
- void main() {
- int flag = 0;
- unsigned long l, h, temp;
- cout << "Enter the lower limit: ";
- cin >> l;
- cout << "Enter the upper limit: ";
- cin >> h;
- if (l % 2 == 0) {
- if (l == 2)
- cout << "2\t";
- l++; // Taking only odd numbers.
- }
- for (; l <= h; l += 2, flag = 0) {
- temp = sqrt(l);
- if (temp % 2 == 0)
- temp++; // Taking only odd numbers.
- for (; temp > 2; temp--) {
- if (l % temp == 0) {
- flag = 1;
- break;
- }
- }
- if (flag == 0)
- cout << l << "\t";
- }
- }
이제 컴파일도 잘 되고 실행도 잘 될 것이다.
그러나 중요한 것은 알고리즘이다. 즉 소수인지 아닌지 확인하는 과정이 최적화되어 있느냐의 문제이다. 위의 소소 코드에서 27~32째 줄의 for 반복문 부분을 살펴보자,
for (; temp > 2; temp--) {
if (l % temp == 0) {
flag = 1;
break;
}
}
예를 들어 l = 3*1999993 = 5999979 인 경우 sqrt(5999979) ≒ 2449.5 이므로,
for 반복문을 시작하면서 temp = 2995 되고 t = 3 이 될 때 까지 무려 1496번을 반복하게 된다.
이 반복문 안의 나눗셈 과정 l % temp 부분을 l % 3 부터 시작하여 l % 5, l % 7, l % 9 ... 이런 식으로 증가시키면서 반복하는 과정으로 진행한다면, l = 3*1999993 = 5999979 인 경우 ㅣ% 3 = 0 이므로 더 이상 반복하지 않고 바로 반복문을 탈출하고 5999979는 소수가 아니라고 판정내린다.
이런 이유로 인하여, 위 소스 코드를 리팩토링하여 다음 처럼 수정하였다.
- #include <iostream>
- #include <cmath>
- using namespace std;
- void main() {
- int flag = 0;
- unsigned long l, h, j, temp;
- cout << "Enter the lower limit: ";
- cin >> l;
- cout << "Enter the upper limit: ";
- cin >> h;
- if (l % 2 == 0) {
- if (l == 2)
- cout << "2\t";
- l++; // Taking only odd numbers.
- }
- for (; l <= h; l += 2, flag = 0) {
- temp = sqrt(l);
- if (temp % 2 == 0)
- temp++; // Taking only odd numbers.
- for (j = 3L; j <= temp; j += 2L) {
- if (l % j == 0L) {
- flag = 1;
- break;
- }
- }
- if (flag == 0)
- cout << l << "\t";
- }
- }
컴파일> cl /GX findPrimes.cpp
실행> findPrimes
Enter the lower limit: 200
Enter the upper limit: 500
211 223 227 229 233 239 241 251 257 263
269 271 277 281 283 293 307 311 313 317
331 337 347 349 353 359 367 373 379 383
389 397 401 409 419 421 431 433 439 443
449 457 461 463 467 479 487 491 499
'프로그래밍 > C++' 카테고리의 다른 글
황금비율(golden ratio) 구하기 with C++ (0) | 2008.03.24 |
---|---|
현재 시각 알아내기 for C++ (0) | 2008.03.24 |
GMP 사용 예제 for C++ (0) | 2008.03.19 |
조립제법(Horner의 방법) 예제 for C++ (0) | 2008.03.14 |
80컬럼 컨솔에 19단표 출력하기 예제 (2) for CPlusPlus (0) | 2008.03.03 |