Eratosthenes篩選法

說到素數,最基本的算是一百以內的那些數了。這些數在數學竟賽中常常會被用到。比如說有這樣一道題:“一百以內有多少在加2後仍然是素數的素數?”11和17就是這樣的素數。如果對素數很熟悉的話,就能迅速得出答案。

那麼,給定一個一百以內的數,如何迅速判斷它是不是素數呢?

一個最簡單的方發就是“埃拉託斯特尼篩法” (Sieve of Eratosthenes)。如上圖所示,給出要篩數值的範圍n,找出n以內的素數p1,p2,,pk。先用2去篩,即把2留下,把2的倍數剔除掉;再用下一個素數,也就是3篩,把3留下,把3的倍數剔除掉;接下去用下一個素數5篩,把5留下,把5的倍數剔除掉;不斷重複下去......。

using System;
using System.Collections.Generic;
using System.Text;

namespace 產生素數
{
    class PrimeGenerator
    {
        private static bool[] crossedOut;
        private static int[] result;
        public static int[] GeneratePrimeNumbers(int maxValue)
        {
            if (maxValue < 2)
            {
                return new int[0];
            }
            else
            {
                UncrossIntegersUpTo(maxValue);
                CrossOutMultiples();
                PutUncrossedIntegersIntoResult();
                return result;
            }
        }

        private static void PutUncrossedIntegersIntoResult()
        {
            result = new int[NumberOfUncrossedIntegers()];
            for (int j = 0, i = 2; i < crossedOut.Length; i++)
            {
                if (NotCrossed(i))
                {
                    result[j++] = i;
                }
            }
        }

        private static bool NotCrossed(int i)
        {
            return crossedOut[i] == false;
        }

        private static int NumberOfUncrossedIntegers()
        {
            int count = 0;
            for(int i=2;i<crossedOut.Length;i++)
            {
                if (NotCrossed(i))
                {
                    count++;
                }
            }
            return count;
        }

        private static void CrossOutMultiples()
        {
            int limit = DetermineIterationLimit();
            for (int i = 2; i <= limit; i++)
            {
                if (NotCrossed(i))
                {
                    CrossOutMultiplesOf(i);
                }
            }
        }

        private static void CrossOutMultiplesOf(int i)
        {
            for(int multiple=2*i;multiple<crossedOut.Length;multiple+=i)
            {
                Console.WriteLine("multiple{0}  {1}", multiple,i);
                crossedOut[multiple] = true;
            }
        }

        private static int DetermineIterationLimit()
        {
            double interationLimit = Math.Sqrt(crossedOut.Length);
              return (int)interationLimit;
        }

        private static void UncrossIntegersUpTo(int maxValue)
        {
            crossedOut = new bool[maxValue + 1];    
            for (int i = 2; i < crossedOut.Length; i++)
            {
                crossedOut[i] = false;
            }
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章