본문 바로가기
IT, 컴퓨터

[C#] 에라토스테네스의 체 알고리즘을 이용한 소수 찾기, 다중 for문과 속도 비교

by 별찌파파 2023. 11. 5.
728x90
반응형
SMALL
반응형

일반적으로 소수는 자기 자신과 1 외에 나누어 떨어지는 수가 없는 수를 의미합니다. 영어로는 프라임 넘버(Prime Numbers)라고 합니다. 소수는 1, 3, 5, 7, 11, 13 이런 식으로 증가를 하는데, 1과 자신 외에는 나눠 떨어지는 수가 없습니다. 소수를 구하기 위해서는 다중 for문을 많이 사용하는데 소수를 구하는데 문제는 없으나 많은 시간이 소요됩니다. 이 소수를 조금 더 효율적으로 구하기 위해서 보통 에라토스테네스의 체 알고리즘을 많이 사용하는데, 오늘은 에라토스테테스의 체 알고리즘을 이용한 코드를 소개해드리겠습니다.

 

에라토스테네스의 체 (Sieve of Eratosthenes)

 

에라토스테네스의 체(Sieve of Eratosthenes)는 소수를 찾는 간단하면서 효과적인 알고리즘 중 하나입니다. 이 알고리즘은 특정 범위 내의 모든 소수를 찾는 데 사용됩니다. 에라토스테네스의 체는 다음과 같이 작동합니다:

  1. 먼저, 소수가 아닌 모든 수를 표시하기 위한 배열을 준비합니다. 이 배열의 크기는 원하는 범위 내의 모든 숫자를 다루기 위한 것입니다.
  2. 시작 숫자 2부터 시작하여, 배열에서 아직 표시되지 않은 가장 작은 수를 찾습니다. 이 수는 소수입니다.
  3. 해당 소수의 배수를 모두 지웁니다. 즉, 해당 소수의 배수들을 표시된 배열에서 삭제하거나 체크하여 소수가 아니라고 표시합니다. 이 단계를 반복하면 모든 배수들이 걸러지게 됩니다.
  4. 다음으로 넘어가서 아직 표시되지 않은 다음 가장 작은 수를 찾고, 해당 수가 소수인 경우 이를 반복합니다.
  5. 반복하면서 표시되지 않은 모든 수를 검사하고, 이 과정을 끝내면 남아 있는 모든 수는 소수입니다.

에라토스테네스의 체 알고리즘은 반복을 통해 지수적으로 증가하는 계산을 방지하고 효율적으로 소수를 찾을 수 있습니다. 이 알고리즘은 주어진 범위 내의 모든 소수를 찾는 데 매우 효과적이며, 컴퓨터 프로그래밍에서 소수 관련 문제를 해결하는 데 널리 사용됩니다.

 

아래는 1에서 5만사이의 소수를 구하는 C# 코드입니다. 언급한 바와 같이 에라토스테네스의 체 알고리즘을 이용한 출력프로그램입니다.

using System;

class PrimeNumbers
{
    static void Main()
    {
        int n = 50000;
        bool[] isPrime = new bool[n + 1];

        // 초기에 모든 수를 소수로 가정
        for (int i = 2; i <= n; i++)
        {
            isPrime[i] = true;
        }

        // 에라토스테네스의 체 알고리즘을 사용하여 소수 찾기
        for (int p = 2; p * p <= n; p++)
        {
            if (isPrime[p] == true)
            {
                for (int i = p * p; i <= n; i += p)
                {
                    isPrime[i] = false;
                }
            }
        }

        // 소수 출력
        Console.WriteLine("1부터 50,000 사이의 소수:");
        for (int i = 2; i <= n; i++)
        {
            if (isPrime[i])
            {
                Console.Write(i + " ");
            }
        }
    }
}

 

위의 코드를 Visual Studio로 작성해 보았습니다.

수행하면 눈 깜짝할 사이에 소수를 출력하는 것을 확인할 수 있습니다. 아마 1초도 안 걸린 것 같네요.

 

다중 for문을 이용한 소수 구하기

 

하지만 에라토스테네스의 체 알고리즘이 아닌 다중 for문으로 구한다면 얼마나 느릴지 테스트해보겠습니다. 아래는 에라토스테네스의 체 알고리즘이 아닌 다중 for문으로 소수를 구하는 코드입니다.

using System;

class PrimeNumbers
{
    static bool IsPrime(int num)
    {
        if (num <= 1)
            return false;
        if (num <= 3)
            return true;
        if (num % 2 == 0 || num % 3 == 0)
            return false;

        for (int i = 5; i * i <= num; i += 6)
        {
            if (num % i == 0 || num % (i + 2) == 0)
                return false;
        }

        return true;
    }

    static void Main()
    {
        Console.WriteLine("1부터 50,000 사이의 소수:");
        for (int i = 1; i <= 50000; i++)
        {
            if (IsPrime(i))
            {
                Console.Write(i + " ");
            }
        }
    }
}

Visual Studio로 작성해서 수행해 보겠습니다.

 

수행결과는 동일하지만 1에서 5만까지 소수를 구하는데 4~5배 정도 느린 것을 알 수 있었습니다. 소수를 빈번하게 구하거나 더 큰 수까지 소수를 구한다면 더욱 수행속도가 느릴 것입니다. 소수를 구하는 데는 에라토스테네스의 체 알고리짐을 이용하는 것을 추천드립니다.

728x90
반응형
LIST