1. 程式人生 > >找質數演算法(Sieve of Eratosthenes篩法)

找質數演算法(Sieve of Eratosthenes篩法)

由於一個合數總是可以分解成若干個質數的乘積,那麼如果把質數(最初只知道2是質數)的倍數都去掉,那麼剩下的就是質數了。
例如要查詢100以內的質數,首先2是質數,把2的倍數去掉;此時3沒有被去掉,可認為是質數,所以把3的倍數去掉;再到5,再到7,7之後呢,因為8,9,10剛才都被去掉了,而100以內的任意合數肯定都有一個因子小於10(100的開方),所以,去掉,2,3,5,7的倍數後剩下的都是質數了。
用程式可以這樣解決,引入布林型別陣列a[i],如果i是質數,a[i]=true,否則a[i]=false。那麼劃掉i可以表示成a[i]=false。
 //找出n以內質數
void Sieve(int n)
        {

            bool[] a = new bool[n+1];
            for (int i = 2; i <= n; i++)  a[i] = true; 
            for (int i = 2; i <= Math.Sqrt(n); i++)
            {
                if (a[i])
                    for (int j = i; j*i <= n; j++) a[j * i] = false;
            }
            for (int i = 0; i <= n; i++)

            {
                if (a[i])
                    Console.Write("{0},",i.ToString());
            }
        }

如果去掉最後一個用來顯示結果的迴圈的話,執行Sieve(10000000)只要1秒多,而上次那個演算法PrimeNum(10000000)卻要71秒多!

/**
 * Solves the challenge by utilizing a Sieve of Eratosthenes (https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
 *
 * @param options
 * @returns {number}
 */
getSolutionViaSieve = function (options) {
    var upperBound = options.upperBound || 0,
        primes = new Array(upperBound),
        primeSum = 0;

    // Initialize all of the numbers from zero to upper bound with a null value.  Later, each index will be checked
    // for null to see if it's been market yet.
    for (var a=0; a<upperBound; a++) {
        primes[a] = null;
    }

    // Iterate from the lowest prime (2) to upperBound to flag prime or not prime.
    for (var i=2; i<upperBound; i++) {

        // Only proceed if the current index hasn't been flagged as prime or not prime.
        if (primes[i] === null) {

            // Flag the current index as prime.
            primes[i] = true;

            // And flag any remaining multiples of this prime as not prime.
            for (var j=i*i; j<upperBound; j+=i) {
                primes[j] = false;
            }
        }
    }

    // Iterate and add up all primes.
    for (var p=0; p<upperBound; p++) {
        if (primes[p] === true) {
            primeSum += p;
        }
    }

    return primeSum;
};

console.log(getSolutionViaSieve({upperBound: 10}));
console.log(getSolutionViaSieve({upperBound: 2000000}));