728x90

소수 구하기 최적의 알고리즘 1편에서 (http://marobiana.tistory.com/89

주어진 수보다 작은 수의 소수들로 나누는게 성능이 좋다고 했었는데,

그것보다 더 좋은 알고리즘을 찾아냈다.ㅋㅋ

이것보다 더 좋은 방법은 아마도 없을 것이라 자신함 !! 

만약 있다면 댓글 달아주시기 바람.


요번에는 c++로 구현해보았음.



1. 알고리즘


에라토스테네스의 체 (Sieve of Eratosthenes)라는 알고리즘이다.

아래 그림을 보면 무엇인지 알 수 있다.





120까지의 모든 소수를 구한다고 해보자.

 

2부터 120까지 배열에 모두 넣은 후

소수가 아닌 것들을 모두 체크해버리는 것이다.


2를 제외한 모든 2의 배수를 체크한다.

3을 제외한 모든 3의 배수를 체크한다.

4는 아까 체크당했으므로 소수 아님.

5를 제외한 모든 5의 배수를 체크한다.

......


체크가 안된 수들이 소수이다.



이 알고리즘을 이용하면, 최악과 최선의 프로그램을 만들어낼 수 있다.



2. 예제


에라토스테네스의 체를 이용해서 구현을 해보겠다.(에라토스테네스...이름 겁나 안외워지는군ㅋㅋㅋㅋㅋㅋ


void getChe1(int num) {

    int *arr;

    arr = (int *) malloc(sizeof(int) * num);

    

    // 입력받은  만큼 배열에 모두 초기화 해둔다

    for (int i = 2; i <= num; i++) {

        arr[i] = i;

    }

    

    for (int i = 2; i <= num; i++) {  // 나누는 값 : i

        for (int j = 2; j <= num; j++) {

            if (arr[j] != i && arr[j] % i == 0) {  // 자신과 같지않고 0으로 떨어지면 소수아님

                arr[j] = 0// 소수가 아닌 경우 0을 넣어둔다

            }

        }

    }

    

    // 출력

    for (int i = 2; i<= num; i++) {

        if (arr[i] != 0)   

            cout << arr[i] << " ";

    }

}


int main(void{

    clock_t start, end;

    

    start = clock();

    getChe1(50000);

    end = clock();

    

    double time = (double)(end - start) / CLOCKS_PER_SEC; 

    cout << "수행시간 : " << time;

}


결과 및 수행시간 >>



어마어마하다. 18초나 걸렸다... ㅋㅋㅋ


1편에서 구현했던 최악의 알고리즘의 3배정도의 시간이 걸렸다.

1편의 최악의 알고리즘의 시간은 아래와 같았다. 6.07415초..




하지만, 에라토스테네스의 체를 잘 이용하면 최상의 소수 구하기 프로그램을 만들 수 있다.



최적의 방법을 생각해내보자..



그것은 바로!


체크할 때, 모든 수를 다 돌면서 체크할 필요 없이

체크 할 배수만큼만 반복문을 돌게하는 것이다.


그리고, 이미 0으로 체크되어버린 수의 배수는 확인하지 않는다.

(왜냐면, 체크된 수의 배수들도 이미 다 체크가 되어있기 때문이다)




예제 >>


void getChe(int num) {

    int *arr;

    arr = (int *)malloc(sizeof(int) * num);

    int i = 2;


    // 입력받은  만큼 배열에 모두 초기화 해둔다

    for (i = 2; i <= num; i++) {

        arr[i] = i;

    }

    

    for (i = 2; i <= num; i++) { 

        if (arr[i] == 0// 이미 체크된 수의 배수는 확인하지 않는다

            continue;

        for (int j = i + i; j <= num; j += i) { // i를 제외한 i의 배수들은 0으로 체크

            arr[j] = 0;

        }

    }


    // print

    for (i = 2; i <= num; i++) {

        if (arr[i] != 0)

            cout << arr[i] << " ";

    }

}



결과 및 수행시간 >>



확 줄었다!! 심지어 1초도 안걸린다.



1편에서 최적의 알고리즘이라고 했던, 특정 수보다 작은 소수들로 나누어보는 알고리즘의 속도는

아래와 같았었다.




이것도 1초는 안걸리지만 에라토스테네스의 체를 이용한 것보단 느린편이다.




그리고 추가적으로..

조금 더 좋게 해보기위해 수학의 공식도 이용을 해보았다 ㅋㅋ

수학자들에 의해 이미 증명된 공식. 좀 간단히 설명하자면,


소수는 n의 배수가 아니어야 한다.

입력받은 수를 입력받은 수보다 작은 수 들로 나누어서 떨어지면 소수가 아니다.

그러나 모두 나누어볼 필요없이, 루트 n 까지만 나누어서 떨어지면 소수가 아니다.



이 이론을 위의 예제와 접목해보면 아래같이 할 수 있다.

나눌 수를 루트 num까지만 돌리는 것~!


 for (i = 2; i <= sqrt(num); i++) { 

        if (arr[i] == 0// 이미 체크된 수의 배수는 확인하지 않는다

            continue;

        for (int j = i + i; j <= num; j += i) { // i를 제외한 i의 배수들은 0으로 체크

            arr[j] = 0;

        }

    }


수행 시간은 아래와 같다.



루트 씌우기 전엔 0.0006489초 였으니 아주 미세한 차이지만 조~~금 더 줄었다 : )




출처: http://marobiana.tistory.com/91 [Take Action]


'ENCRYPTION' 카테고리의 다른 글

machine epsilon  (0) 2018.12.05
C round-off problem  (0) 2018.12.05
Memory Leak And Memory maintenance  (0) 2018.12.03
C Program to Implement Sieve of eratosthenes to Generate Prime Numbers Between Given Range  (0) 2018.12.03
메르센 소수  (0) 2018.12.03
728x90
This C program is used to implement Sieve of Eratosthenes to generate prime numbers between given range. The Sieve of Eratosthenes is a simple algorithm that finds the prime numbers up to a given integer. Implement this algorithm, with the only allowed optimization that the outer loop can stop at the square root of the limit, and the inner loop may start at the square of the prime just found. That means especially that you shouldn’t optimize by using pre-computed wheels, i.e. don’t assume you need only to cross out odd numbers (wheel based on 2), numbers equal to 1 or 5 modulo 6 (wheel based on 2 and 3), or similar wheels based on low primes.

Here is the source code of the C program to generate prime numbers. The C program is successfully compiled and run on a Linux system. The program output is also shown below.

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #define limit 100 /*size of integers array*/
  5.  
  6. int main(){
  7.     unsigned long long int i,j;
  8.     int *primes;
  9.     int z = 1;
  10.  
  11.     primes = malloc(sizeof(int) * limit);
  12.  
  13.     for (i = 2;i < limit; i++)
  14.         primes[i] = 1;
  15.  
  16.     for (i = 2;i < limit; i++)
  17.         if (primes[i])
  18.             for (j = i;i * j < limit; j++)
  19.                 primes[i * j] = 0;
  20.  
  21.     printf("\nPrime numbers in range 1 to 100 are: \n");
  22.     for (i = 2;i < limit; i++)
  23.         if (primes[i])
  24.             printf("%d\n", i);
  25.  
  26. return 0;
  27. }

$ gcc prime.c -o prime
$ ./prime
 
Prime numbers in range 1 to 100 are: 
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97


'ENCRYPTION' 카테고리의 다른 글

machine epsilon  (0) 2018.12.05
C round-off problem  (0) 2018.12.05
Memory Leak And Memory maintenance  (0) 2018.12.03
Sieve of Eratosthenes  (0) 2018.12.03
메르센 소수  (0) 2018.12.03
728x90

메르센 소수

위키백과, 우리 모두의 백과사전.
둘러보기로 가기검색하러 가기

메르센 수(Mersenne number)는 2의 거듭제곱에서 1이 모자란 숫자를 가리킨다. 지수 에 대한 메르센 수는 로 나타내고 목록은 아래와 같다.

13715316312725551110232047409581911638332767... (OEIS의 수열 A000225)

메르센 소수(Mersenne prime)는 메르센 수 중에서 소수인 수이다. 예를 들면 3과 7은 둘 다 소수이고 이므로 3과 7은 둘 다 메르센 소수이다. 반대로 은 소수가 아니다. 현대에 알려진 매우 큰 소수들 중에는 메르센 소수가 상당히 많다.

3731127819113107152428721474836472305843009213693951... (OEIS의 수열 A000668)

메르센 소수가 무한히 많이 존재하는지 아니면 그 개수가 정해져 있는지는 아직 알려져 있지 않다.

메르센 수의 속성[편집]

메르센 수는 다음의 몇 가지 속성을 지닌다. :

은 이항계수의 에서 1을 뺀 값이다.

메르센 수의 속성 2[편집]

메르센 수의 지수가 홀수소수 이면 소인수의 형태는 다음과 같음을 페르마가 증명하였다.

 (는 음이 아닌 정수)

이것은 메르센 수가 소수, 즉 메르센 소수일때도 성립한다.

메르센 소수에 관한 정리[편집]

  • 1) 만일 이 하나의 양의 정수이면, 이항정리에 의해 다음과 같이 쓸 수 있다:

또는

이다( =  = 로,  = 로 놓았을 때).

증명

역사[편집]

1644년 마랭 메르센은  형태가 소수가 되는 것은,  일 때  뿐이라고 발표하였다. 그러나 그 주장의 일부는 잘못임이 밝혀졌다. 목록에 포함되지 않은 는 소수이며, 목록에 포함되어 있는 는 합성수이다.

리젤 수의 발견자이기도 한 스웨덴의 수학자인 한스 리젤이 1957년에 컴퓨터를 이용하여 18번째의 메르센 소수를 발견한 이래, 이후 컴퓨터를 활용하여 새로운 메르센 소수를 찾고 있다.

메르센 소수 찾기[편집]

 다음 등식은 이 메르센 소수가 되기 위해서는  자신이 소수여야 한다는 것을 알려준다.

따라서, 메르센 소수를 찾기 위해서는 지수가 소수인 경우만 조사하면 되지만, 일반적으로 그 역은 참이 아니다. 즉 이 소수라고 하여  또한 소수인 것은 아니다. 예를 들어, 11은 소수지만 로 소인수분해된다.

메르센 소수 목록[편집]

현재까지 발견한 메르센 소수 표 (OEIS의 수열 A000668):

#의 자리수발견일발견자
1231기원전 430년 경고대 그리스 수학자
2371기원전 430년 경고대 그리스 수학자
35312기원전 300년 경고대 그리스 수학자
471273기원전 300년 경고대 그리스 수학자
513819141456년아무개
61713107161588년피에트로 카탈디
71952428761588년피에트로 카탈디
8312147483647101772년레온하르트 오일러
9612305843009213693951191883년이반 미흐비치 페르부쉰
1089618970019…449562111271911년R. E. Powers
11107162259276…010288127331914년R. E. Powers
12127170141183…884105727391876년에두아르 뤼카
13521686479766…1150571511571952년 1월 30일라파헬 로빈슨
14607531137992…0317281271831952년 1월 30일라파헬 로빈슨
151,279104079321…1687290873861952년 6월 25일라파헬 로빈슨
162,203147597991…6977710076641952년 10월 7일라파헬 로빈슨
172,281446087557…1328363516871952년 10월 9일라파헬 로빈슨
183,217259117086…9093150719691957년 9월 8일한스 리젤
194,253190797007…3504849911,2811961년 11월 3일알렉산더 허비츠
204,423285542542…6085806071,3321961년 11월 3일알렉산더 허비츠
219,689478220278…2257541112,9171963년 5월 11일도널드 길리스
229,941346088282…7894635512,9931963년 5월 16일도널드 길리스
2311,213281411201…6963921913,3761963년 6월 2일도널드 길리스
2419,937431542479…9680414716,0021971년 3월 4일브리언트 터커맨
2521,701448679166…5118827516,5331978년 10월 30일랜돈 커트 놀과 로라 니켈
2623,209402874115…7792645116,9871979년 2월 9일랜돈 커트 놀
2744,497854509824…01122867113,3951979년 4월 8일해리 넬슨과 데이빗 슬로빈스키
2886,243536927995…43343820725,9621982년 9월 25일데이빗 슬로빈스키
29110,503521928313…46551500733,2651988년 1월 28일월크 콜킷과 루크 웰시
30132,049512740276…73006131139,7511983년 9월 19일[1]데이빗 슬로빈스키
31216,091746093103…81552844765,0501985년 9월 1일[1]데이빗 슬로빈스키
32756,839174135906…544677887227,8321992년 2월 19일데이빗 슬로빈스키와 폴 게이지
33859,433129498125…500142591258,7161994년 1월 4일데이빗 슬로빈스키와 폴 게이지
341,257,787412245773…089366527378,6321996년 9월 3일데이빗 슬로빈스키와 폴 게이지 [1]
351,398,269814717564…451315711420,9211996년 11월 13일GIMPS / 조엘 아르멩고 [2][깨진 링크(과거 내용 찾기)]
362,976,221623340076…729201151895,9321997년 8월 24일GIMPS / 고든 스펜스 [3][깨진 링크(과거 내용 찾기)]
373,021,377127411683…024694271909,5261998년 1월 27일GIMPS / 롤랜드 클락슨 [4][깨진 링크(과거 내용 찾기)]
386,972,593437075744…9241937912,098,9601999년 6월 11일GIMPS / 난야 하이라트왈라 [5]
3913,466,917924947738…2562590714,053,9462001년 11월 14일GIMPS / 마이클 카메론 [6]
4020,996,011125976895…8556820476,320,4302003년 11월 17일GIMPS / 마이클 셰이퍼 [7]
4124,036,583299410429…7339694077,235,7332004년 5월 15일GIMPS / 조지 핀들리 [8]
4225,964,951122164630…5770772477,816,2302005년 2월 18일GIMPS / 마르틴 노바크 [9]
43*30,402,457315416475…6529438719,152,0522005년 9월 15일GIMPS / 커티스 쿠퍼와 스티븐 분 [10]
44*32,582,657124575026…0539678719,808,3582006년 9월 4일GIMPS / 커티스 쿠퍼와 스티븐 분 [11]
45*37,156,667202254406…30822092711,185,2722008년 9월 6일GIMPS / Hans-Michael Elvenich [12]
46*42,643,801169873516…56231475112,837,0642009년 4월 12일**GIMPS / Odd Magnar Strindmo
47*43,112,609316470269…69715251112,978,1892008년 8월 23일GIMPS / Edson Smith [13]
48*57,885,161581887266…72428595117,425,1702013년 1월 25일GIMPS / Curtis Cooper [14]
49*74,207,281300376418…08643635122,338,6182015년 9월 17일***GIMPS / Curtis Cooper [15]
5077,232,917467333183…76217907123,249,4252017년 12월 26일GIMPS / Jon Pace

44번째 알려진 메르센 소수를 시각적으로 보여 주기 위해서는 1페이지 당, 10진수 75개 자리수의 숫자를 50줄씩 쓴 2,616페이지가 필요하다.

*표의 43번째 수인 과 49번째 수인  사이에 아직 발견되지 않은 다른 메르센 소수가 있는지는 아직 알려져 있지 않다. 따라서 이 번호들은 바뀔 수도 있다. 소수가 작은 소수부터 순차적으로 발견되는 것은 아니다. 예를 들어, 29번째 메르센 소수는 30번째와 31번째 소수의 발견 이후에 발견되었다.

**M42,643,801는 2009년 4월 12일 컴퓨터에 의해 처음 발견되었다. 그러나 6월 4일까지 이 사실을 인지한 사람은 아무도 없었다. 그래서, 발견일을 4월 12일 또는 6월 4일로 간주한다. 발견자 스트린드모(Strindmo)는 alias Stig M. Valstad를 사용한 것으로 보인다.

***M74,207,281는 2015년 9월 17일 컴퓨터에 의해 처음 발견되었다. 그러나 2016년 1월 7일까지 이 사실을 인지한 사람은 아무도 없었다. 그래서, 발견일을 2015년 9월 17일 또는 2016년 1월 7일로 간주한다.

완전수[편집]

메르센 소수는 완전수와 여러 관련성이 있어 흥미롭다. 기원전 4세기에 유클리드는 이 메르센 소수이면 다음과 같이 짝수 완전수임을 보였다.

18세기에 오일러는 모든 짝수 완전수는 이와 같은 형태를 갖는다는 것을 증명했다. 홀수 완전수는 아직 발견되지 않았으며 존재하지 않는 것으로 추측된다.

일반화[편집]

의 2진법 표현은 숫자 1이 번 반복된다. 예를 들면, 25 - 1 = 111112와 같이 표기된다. 그러므로 메르센 소수는 2를 밑으로 하는 단위 반복 소수이다.

관련 항목[편집]

각주[편집]

외부 링크[편집]


'ENCRYPTION' 카테고리의 다른 글

machine epsilon  (0) 2018.12.05
C round-off problem  (0) 2018.12.05
Memory Leak And Memory maintenance  (0) 2018.12.03
Sieve of Eratosthenes  (0) 2018.12.03
C Program to Implement Sieve of eratosthenes to Generate Prime Numbers Between Given Range  (0) 2018.12.03

+ Recent posts