Πιο αποτελεσματικό κώδικα για τα πρώτα 10.000 πρώτοι αριθμοί;

ψήφοι
49

Θέλω να εκτυπώσετε τα πρώτα 10000 πρώτοι αριθμοί. Μπορεί κάποιος να μου δώσει την πιο αποδοτικό κώδικα για αυτό; διευκρινίσεις:

  1. Δεν έχει σημασία αν ο κωδικός σας είναι αναποτελεσματική για n> 10000.
  2. Το μέγεθος του κώδικα δεν έχει σημασία.
  3. Δεν μπορείτε απλά δύσκολο κωδικοποιήσει τις τιμές με οποιονδήποτε τρόπο.
Δημοσιεύθηκε 03/08/2008 στις 06:45
πηγή χρήστη
Σε άλλες γλώσσες...                            


29 απαντήσεις

ψήφοι
41

Το Κόσκινο του Atkin είναι ίσως αυτό που ψάχνετε, ανώτερο όριο χρόνου λειτουργίας του θα είναι O (N / log log N).

Αν τρέχετε μόνο τους αριθμούς 1 ολοένα και 1 μικρότερο από τα πολλαπλάσια του 6, θα μπορούσε να είναι ακόμη πιο γρήγορα, όπως όλοι οι πρώτοι αριθμοί πάνω από το 3 είναι 1 μακριά από κάποιο πολλαπλάσιο του έξι. Πόρων για τη δήλωσή μου

Απαντήθηκε 03/08/2008 στις 07:03
πηγή χρήστη

ψήφοι
4

Δεν είναι αποτελεσματική σε όλους, αλλά μπορείτε να χρησιμοποιήσετε μια κανονική έκφραση για να ελέγξετε για πρώτους αριθμούς.

/^1?$|^(11+?)\1+$/

Αυτό ελέγχει εάν, για μια σειρά που αποτελείται από k « 1» s, k είναι Not Prime (δηλαδή εάν η συμβολοσειρά αποτελείται από ένα « 1» ή οποιοδήποτε αριθμό των « 1» s που μπορεί να εκφραστεί ως ένα n -ary προϊόντος).

Απαντήθηκε 03/08/2008 στις 19:52
πηγή χρήστη

ψήφοι
4

Έχω προσαρμοστεί κώδικα που βρέθηκαν στο CodeProject για να δημιουργήσετε το παρακάτω:

ArrayList primeNumbers = new ArrayList();

for(int i = 2; primeNumbers.Count < 10000; i++) {
    bool divisible = false;

    foreach(int number in primeNumbers) {
        if(i % number == 0) {
            divisible = true;
        }
    }

    if(divisible == false) {
        primeNumbers.Add(i);
        Console.Write(i + " ");
    }
}

Δοκιμή αυτό στο ASP.NET μου διακομιστή πήρε το rountine περίπου 1 λεπτό για να τρέξει.

Απαντήθηκε 05/08/2008 στις 20:55
πηγή χρήστη

ψήφοι
35

Θα ήθελα να συστήσω ένα κόσκινο, είτε το Κόσκινο του Ερατοσθένη ή το κόσκινο του Atkin.

Το κόσκινο ή Ερατοσθένη είναι ίσως το πιο έξυπνο τρόπο για την εξεύρεση μια λίστα των πρώτων αριθμών. Βασικά σας:

  1. Γράψτε κάτω μια λίστα με τους αριθμούς από 2 σε ό, τι όριο που θέλετε, ας πούμε 1000.
  2. Πάρτε τον πρώτο αριθμό που δεν διασχίζεται από (για την πρώτη επανάληψη είναι 2) και διαγράφω όλα τα πολλαπλάσια του αριθμού αυτού από τη λίστα.
  3. Επαναλάβετε το βήμα 2 μέχρι να φτάσετε στο τέλος της λίστας. Όλοι οι αριθμοί που δεν έχουν περάσει από τα prime.

Προφανώς υπάρχουν αρκετές βελτιστοποιήσεις που μπορούν να γίνουν για να κάνουν αυτό το έργο αλγόριθμο πιο γρήγορα, αλλά αυτή είναι η βασική ιδέα.

Το κόσκινο του Atkin χρησιμοποιεί μια παρόμοια προσέγγιση, αλλά, δυστυχώς, δεν ξέρω αρκετά για να σας το εξηγήσω. Αλλά εγώ ξέρω ότι ο αλγόριθμος που συνδέεται διαρκεί 8 δευτερόλεπτα για να καταλάβω όλες τις πρώτους έως 1000000000 πάνω σε αρχαίο Pentium II-350

Κόσκινο του Ερατοσθένη πηγαίου κώδικα: http://web.archive.org/web/20140705111241/http://primes.utm.edu/links/programs/sieves/Eratosthenes/C_source_code/

Κόσκινο του Atkin πηγαίου κώδικα: http://cr.yp.to/primegen.html

Απαντήθηκε 06/08/2008 στις 00:49
πηγή χρήστη

ψήφοι
3

Κόσκινο του Ερατοσθένη είναι ο τρόπος να πάει, λόγω του ότι είναι η απλότητα και την ταχύτητα. Εφαρμογή μου σε C

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

int main(void)
{
    unsigned int lim, i, j;

    printf("Find primes upto: ");
    scanf("%d", &lim);
    lim += 1;
    bool *primes = calloc(lim, sizeof(bool));

    unsigned int sqrtlim = sqrt(lim);
    for (i = 2; i <= sqrtlim; i++)
        if (!primes[i])
            for (j = i * i; j < lim; j += i)
                primes[j] = true;

    printf("\nListing prime numbers between 2 and %d:\n\n", lim - 1);
    for (i = 2; i < lim; i++)
        if (!primes[i])
            printf("%d\n", i);

    return 0;
}

CPU Ώρα να βρούμε πρώτους αριθμούς (για Pentium Dual Core E2140 1,6 GHz, χρησιμοποιώντας ενιαίο πυρήνα)

~ 4s για lim = 100.000.000

Απαντήθηκε 21/08/2008 στις 00:45
πηγή χρήστη

ψήφοι
11

GateKiller , πώς για την προσθήκη ενός breakμε εκείνη ifστο foreachβρόχο; Αυτό θα επιταχύνει τα πράγματα πολύ , διότι αν, όπως 6 διαιρείται με το 2 δεν χρειάζεται να ελέγξει με 3 και 5. (θα ήθελα να ψηφίσω λύση σας έτσι κι αλλιώς, αν είχα αρκετή φήμη :-) ...)

ArrayList primeNumbers = new ArrayList();

for(int i = 2; primeNumbers.Count < 10000; i++) {
    bool divisible = false;

    foreach(int number in primeNumbers) {
        if(i % number == 0) {
            divisible = true;
            break;
        }
    }

    if(divisible == false) {
        primeNumbers.Add(i);
        Console.Write(i + " ");
    }
}
Απαντήθηκε 27/08/2008 στις 21:26
πηγή χρήστη

ψήφοι
7

Χρησιμοποιώντας GMP, θα μπορούσε κανείς να γράψει τα εξής:

#include <stdio.h>
#include <gmp.h>

int main() {
  mpz_t prime;
  mpz_init(prime);
  mpz_set_ui(prime, 1);
  int i;
  char* num = malloc(4000);
  for(i=0; i<10000; i++) {
    mpz_nextprime(prime, prime);
    printf("%s, ", mpz_get_str(NULL,10,prime));
  }
}

Σε 2.33GHz μου Macbook Pro, εκτελεί τα εξής:

time ./a.out > /dev/null

real    0m0.033s
user    0m0.029s
sys    0m0.003s

Υπολογισμός 1.000.000 πρώτοι στον ίδιο φορητό υπολογιστή:

time ./a.out > /dev/null

real    0m14.824s
user    0m14.606s
sys     0m0.086s

GMP είναι ιδιαίτερα αισιόδοξος για αυτό το είδος του πράγματος. Αν δεν θέλετε πραγματικά να κατανοήσουμε τους αλγόριθμους γράφοντας τη δική σας, θα πρέπει να συμβουλεύονται να χρησιμοποιούν libGMP υπό C.

Απαντήθηκε 29/08/2008 στις 08:06
πηγή χρήστη

ψήφοι
17

Αυτό δεν είναι αυστηρά σε σχέση με τον περιορισμό ενσωματώνουμε, αλλά έρχεται τρομερά κοντά. Γιατί να μην κάνετε λήψη κάποιου προγράμματος αυτήν τη λίστα και να το τυπώσετε έξω, αντ 'αυτού;

http://primes.utm.edu/lists/small/10000.txt

Απαντήθηκε 31/08/2008 στις 23:20
πηγή χρήστη

ψήφοι
9

@Matt: log (log (10000)) είναι ~ 2

Από το άρθρο της Wikipedia (η οποία θα αναφέρεται) Κόσκινο του Atkin :

Αυτό κόσκινο υπολογίζει πρώτους μέχρι Ν χρησιμοποιώντας O(N/log log N)λειτουργίες με μόνο Ν 1/2 + o (1) bits της μνήμης. Αυτό είναι λίγο καλύτερο από το κόσκινο του Ερατοσθένη που χρησιμοποιεί O(N) λειτουργίες και O (N 1/2 (log log N) / log N) bits της μνήμης (AOL Atkin, DJ Bernstein, 2004) . Αυτές ασυμπτωτική υπολογιστική πολυπλοκότητα περιλαμβάνουν απλά βελτιστοποιήσεις, όπως παραγοντοποίηση τροχό, και τη διάσπαση του υπολογισμού σε μικρότερα μπλοκ.

Δεδομένου ασυμπτωτική υπολογιστική πολυπλοκότητα μαζί O(N)(για Ερατοσθένης) και O(N/log(log(N)))(για Atkin) δεν μπορούμε να πούμε (για μικρά N=10_000) η οποία αλγόριθμο, αν εφαρμοστούν, θα είναι ταχύτερη.

Achim Flammenkamp έγραψε το κόσκινο του Ερατοσθένη :

που παραθέτει:

@ NUM1

Για διαστήματα μεγαλύτερα περίπου 10 ^ 9, σίγουρα για εκείνους> 10 ^ 10, το Κόσκινο του Ερατοσθένη είναι πολύ καλύτερες επιδόσεις από το κόσκινο της Atkins και Bernstein η οποία χρησιμοποιεί αμείωτη δυαδικό τετραγωνικές μορφές. Δείτε το χαρτί τους για πληροφορίες υποβάθρου, καθώς και της παραγράφου 5 του Δρ W. του Galway ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ.

Ως εκ τούτου για 10_000Κόσκινο του Ερατοσθένη μπορεί να είναι ταχύτερη τότε Κόσκινο του Atkin.

Για να απαντήσετε ΕΠ ο κωδικός prime_sieve.c (αναφέρεται από num1)

Απαντήθηκε 06/10/2008 στις 21:03
πηγή χρήστη

ψήφοι
2

Προσαρμογή και σε συνέχεια της από GateKiller , εδώ είναι η τελική έκδοση που έχω χρησιμοποιήσει.

    public IEnumerable<long> PrimeNumbers(long number)
    {
        List<long> primes = new List<long>();
        for (int i = 2; primes.Count < number; i++)
        {
            bool divisible = false;

            foreach (int num in primes)
            {
                if (i % num == 0)
                    divisible = true;

                if (num > Math.Sqrt(i))
                    break;
            }

            if (divisible == false)
                primes.Add(i);
        }
        return primes;
    }

Είναι βασικά η ίδια, αλλά έχω προσθέσει την πρόταση «σπάνε Sqrt» και να αλλάξει κάποια από τις μεταβλητές γύρω για να το κάνει να ταιριάζει καλύτερα για μένα. (Ήμουν εργάζονται για Euler και χρειάζεται την 10001th προνομιακή)

Απαντήθηκε 16/02/2009 στις 06:17
πηγή χρήστη

ψήφοι
2

Το κόσκινο φαίνεται να είναι η λάθος απάντηση. Το κόσκινο σας δίνει τις πρώτους μέχρι έναν αριθμό Ν , όχι τα πρώτα Ν πρώτων αριθμών. Εκτέλεση @Imran ή @Andrew Szeto, και μπορείτε να πάρετε τις πρώτους μέχρι Ν

Το κόσκινο μπορεί να εξακολουθεί να μπορούν να χρησιμοποιηθούν, αν συνεχίσουμε να προσπαθούμε κόσκινα για όλο και μεγαλύτερους αριθμούς μέχρι να χτυπήσει ένα ορισμένο μέγεθος σύνολο των αποτελεσμάτων σας, και να χρησιμοποιήσετε κάποια προσωρινή αποθήκευση των αριθμών που έχουν ήδη ληφθεί, αλλά πιστεύω ότι θα εξακολουθεί να μην υπάρχει πιο γρήγορα να είναι από μια λύση, όπως @ Πέτρου .

Απαντήθηκε 19/06/2009 στις 19:12
πηγή χρήστη

ψήφοι
3

Εδώ είναι ένα κόσκινο του Ερατοσθένη που έγραψα στο PowerShell πριν από λίγες ημέρες. Έχει μια παράμετρο για τον προσδιορισμό του αριθμού των πρώτων αριθμών που θα πρέπει να επιστραφούν.

#
# generate a list of primes up to a specific target using a sieve of eratosthenes
#
function getPrimes { #sieve of eratosthenes, http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
    param ($target,$count = 0)
    $sieveBound = [math]::ceiling(( $target - 1 ) / 2) #not storing evens so count is lower than $target
    $sieve = @($false) * $sieveBound
    $crossLimit = [math]::ceiling(( [math]::sqrt($target) - 1 ) / 2)
    for ($i = 1; $i -le $crossLimit; $i ++) {
        if ($sieve[$i] -eq $false) {
            $prime = 2 * $i + 1
            write-debug "Found: $prime"
            for ($x = 2 * $i * ( $i + 1 ); $x -lt $sieveBound; $x += 2 * $i + 1) {
                $sieve[$x] = $true
            }
        }
    }
    $primes = @(2)
    for ($i = 1; $i -le $sieveBound; $i ++) {
        if($count -gt 0 -and $primes.length -ge $count) {
            break;
        }
        if($sieve[$i] -eq $false) {
            $prime = 2 * $i + 1
            write-debug "Output: $prime"
            $primes += $prime
        }
    }
    return $primes
}
Απαντήθηκε 07/09/2009 στις 19:52
πηγή χρήστη

ψήφοι
2

Στην Python

import gmpy
p=1
for i in range(10000):
    p=gmpy.next_prime(p)
    print p 
Απαντήθηκε 22/02/2010 στις 08:45
πηγή χρήστη

ψήφοι
0

Έχω γράψει αυτό το χρησιμοποιούν python, όπως μόλις άρχισε να μαθαίνει αυτό, και λειτουργεί απολύτως εντάξει. Η προνομιακή 10,000th παράγουν από αυτό τον κωδικό, όπως αυτά που αναφέρονται στο http://primes.utm.edu/lists/small/10000.txt . Για να ελέγξετε αν nείναι πρώτος ή όχι, χάσμα nμε τους αριθμούς από το 2να sqrt(n). Εάν οποιαδήποτε από αυτό το εύρος του αριθμού χωρίζει τέλεια nτότε δεν είναι προνομιακή.

import math
print ("You want prime till which number??")
a = input()
a = int(a)
x = 0
x = int(x)
count = 1
print("2 is prime number")
for c in range(3,a+1):
    b = math.sqrt(c)
    b = int(b)
    x = 0
    for b in range(2,b+1):
        e  = c % b
        e = int(e)
        if (e == 0):
            x = x+1
    if (x == 0):
        print("%d is prime number" % c)
        count = count + 1
print("Total number of prime till %d is %d" % (a,count))
Απαντήθηκε 27/12/2010 στις 18:37
πηγή χρήστη

ψήφοι
1

Εδώ είναι ο κωδικός μου VB 2008, η οποία βρίσκει όλα primes <10.000.000 σε 1 λεπτό 27 δευτερόλεπτα για το laptop δουλειά μου. Είναι παραλείπει ακόμα και αριθμούς και αναζη