Is there a simple algorithm that can determine if X is prime?

后端 未结 16 1491
离开以前
离开以前 2020-12-01 00:32

I have been trying to work my way through Project Euler, and have noticed a handful of problems ask for you to determine a prime number as part of it.

  1. I kno

相关标签:
16条回答
  • 2020-12-01 01:02

    Here's a simple optimization of your method that isn't quite the Sieve of Eratosthenes but is very easy to implement: first try dividing X by 2 and 3, then loop over j=1..sqrt(X)/6, trying to divide by 6*j-1 and 6*j+1. This automatically skips over all numbers divisible by 2 or 3, gaining you a pretty nice constant factor acceleration.

    0 讨论(0)
  • 2020-12-01 01:03

    Your right the simples is the slowest. You can optimize it somewhat.

    Look into using modulus instead of square roots. Keep track of your primes. you only need to divide 7 by 2, 3, and 5 since 6 is a multiple of 2 and 3, and 4 is a multiple of 2.

    Rslite mentioned the eranthenos sieve. It is fairly straight forward. I have it in several languages it home. Add a comment if you want me to post that code later.


    Here is my C++ one. It has plenty of room to improve, but it is fast compared to the dynamic languages versions.

    // Author: James J. Carman
    // Project: Sieve of Eratosthenes
    // Description: I take an array of 2 ... max values. Instead of removeing the non prime numbers,
    // I mark them as 0, and ignoring them.
    // More info: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
    #include <iostream>
    
    int main(void) {
            // using unsigned short.
            // maximum value is around 65000
            const unsigned short max = 50000;
            unsigned short x[max];
            for(unsigned short i = 0; i < max; i++)
                    x[i] = i + 2;
    
            for(unsigned short outer = 0; outer < max; outer++) {
                    if( x[outer] == 0)
                            continue;
                    unsigned short item = x[outer];
                    for(unsigned short multiplier = 2; (multiplier * item) < x[max - 1]; multiplier++) {
                            unsigned int searchvalue = item * multiplier;
                            unsigned int maxValue = max + 1;
                            for( unsigned short maxIndex = max - 1; maxIndex > 0; maxIndex--) {
                                    if(x[maxIndex] != 0) {
                                            maxValue = x[maxIndex];
                                            break;
                                    }
                            }
                            for(unsigned short searchindex = multiplier; searchindex < max; searchindex++) {
                                    if( searchvalue > maxValue )
                                            break;
                                    if( x[searchindex] == searchvalue ) {
                                            x[searchindex] = 0;
                                            break;
                                    }
                            }
                    }
            }
            for(unsigned short printindex = 0; printindex < max; printindex++) {
                    if(x[printindex] != 0)
                            std::cout << x[printindex] << "\t";
            }
            return 0;
    }
    

    I will throw up the Perl and python code I have as well as soon as I find it. They are similar in style, just less lines.

    0 讨论(0)
  • 2020-12-01 01:04

    I like this python code.

    def primes(limit) :
        limit += 1
        x = range(limit)
        for i in xrange(2,limit) :
            if x[i] ==  i:
                x[i] = 1
                for j in xrange(i*i, limit, i) :
                    x[j] = i
        return [j for j in xrange(2, limit) if x[j] == 1]
    

    A variant of this can be used to generate the factors of a number.

    def factors(limit) :
        limit += 1
        x = range(limit)
        for i in xrange(2,limit) :
            if x[i] == i:
                x[i] = 1
                for j in xrange(i*i, limit, i) :
                    x[j] = i
        result = []
        y = limit-1
        while x[y] != 1 :
            divisor = x[y]
            result.append(divisor)
            y /= divisor
        result.append(y)
        return result
    

    Of course, if I were factoring a batch of numbers, I would not recalculate the cache; I'd do it once and do lookups in it.

    0 讨论(0)
  • 2020-12-01 01:07

    For reasonably small numbers, x%n for up to sqrt(x) is awfully fast and easy to code.

    Simple improvements:

    test 2 and odd numbers only.

    test 2, 3, and multiples of 6 + or - 1 (all primes other than 2 or 3 are multiples of 6 +/- 1, so you're essentially just skipping all even numbers and all multiples of 3

    test only prime numbers (requires calculating or storing all primes up to sqrt(x))

    You can use the sieve method to quickly generate a list of all primes up to some arbitrary limit, but it tends to be memory intensive. You can use the multiples of 6 trick to reduce memory usage down to 1/3 of a bit per number.

    I wrote a simple prime class (C#) that uses two bitfields for multiples of 6+1 and multiples of 6-1, then does a simple lookup... and if the number i'm testing is outside the bounds of the sieve, then it falls back on testing by 2, 3, and multiples of 6 +/- 1. I found that generating a large sieve actually takes more time than calculating primes on the fly for most of the euler problems i've solved so far. KISS principle strikes again!

    I wrote a prime class that uses a sieve to pre-calculate smaller primes, then relies on testing by 2, 3, and multiples of six +/- 1 for ones outside the range of the sieve.

    0 讨论(0)
提交回复
热议问题