2010-09-27 17 views
7

Po pierwsze - dużo sprawdziłem na tym forum i nie znalazłem wystarczająco szybko wystarczająco szybko. Próbuję utworzyć funkcję, która zwróci mi liczby pierwsze w określonym zakresie. Na przykład zrobiłem tę funkcję (w języku C#) za pomocą sita Eratostenesa. Próbowałem też sito Atkin, ale jeden Eratosthenes działa szybciej (w moim realizacji):Szybki algorytm wyszukiwania liczb pierwszych?

public static void SetPrimesSieve(int Range) 
    { 
     Primes = new List<uint>(); 
     Primes.Add(2); 
     int Half = (Range - 1) >> 1; 
     BitArray Nums = new BitArray(Half, false); 
     int Sqrt = (int)Math.Sqrt(Range); 
     for (int i = 3, j; i <= Sqrt;) 
     { 
      for (j = ((i * i) >> 1) - 1; j < Half; j += i) 
       Nums[j] = true; 
      do 
       i += 2; 
      while (i <= Sqrt && Nums[(i >> 1) - 1]); 
     } 
     for (int i = 0; i < Half; ++i) 
      if (!Nums[i]) 
       Primes.Add((uint)(i << 1) + 3); 
    } 

Biegnie około dwa razy szybciej niż kody & algorytmów znalazłem ... Tam powinien być szybszy sposób na znalezienie liczb pierwszych, czy mógłbyś mi pomóc?

+1

In w jakim zakresie szukasz liczb pierwszych? Tylko od 0 do maks. Int? Jak szeroki jest zasięg? – Gleno

+0

Załóżmy, że coś podobnego do miliarda/2 – Ohad

+6

Istnieje 50M liczb pierwszych mniejszych niż 10^9, więc ich wstępne obliczenia dałyby tabelę o wielkości 200 MB. W rzeczywistości przechowywanie sita byłoby mniejsze (10^9 bitów to 125MB, a ty nie musisz przechowywać bitów parzystych, abyś mógł zmieścić to wszystko poniżej 64 MB). – Gabe

Odpowiedz

9

Szukając algorytmów na ten temat (dla projektu Euler), nie pamiętam, aby coś było szybciej. Jeśli prędkość naprawdę jest problemem, czy myślałeś o przechowywaniu liczb pierwszych, więc po prostu trzeba to sprawdzić?

EDYCJA: szybkie wyszukiwanie google znalezione this, potwierdzające, że najszybszą metodą byłoby po prostu wyświetlenie wyników i sprawdzenie ich w razie potrzeby.

Jeszcze jedna edycja - możesz znaleźć więcej informacji here, w zasadzie duplikat tego tematu. Główny słupek stwierdza, że ​​sito Atkina było szybsze niż ery, jeśli chodzi o generowanie w locie.

+0

Nie, te nie są szybkie, nawet mój kod jest szybszy. Naprawdę widziałem coś, co mówi, że jest bardzo szybko (w pewnym sensie nie ufam temu ...) Sprawdzę to jutro, muszę iść. dzięki i tak. (to nie jest duplikat drugiego tematu, były powolne odpowiedzi) – Ohad

+0

To jest niesamowity artykuł, +1 –

+0

są algorytmy bardzo bardzo szybsze niż ten prosty, zobacz moją odpowiedź –

0

Kilka komentarzy.

  1. Aby uzyskać prędkość, wykonaj wstępne obliczenia, a następnie załaduj z dysku. Jest super szybki. Zrobiłem to w Javie już dawno temu.

  2. Nie przechowuj jako tablicy, przechowuj jako bitową dla liczb nieparzystych. Sposób bardziej efektywny w pamięci

  3. Jeśli prędkość pytanie jest, że chcesz to zwłaszcza obliczenia szybko biegać (trzeba uzasadniać, dlaczego nie można wcześniej obliczyć i załadować go z dysku) trzeba kodować sito lepszego Atkin użytkownika. To jest szybsze. Ale tylko nieznacznie.

  4. Nie wskazałeś zastosowania końcowego dla tych liczb pierwszych. Możliwe, że czegoś kompletnie brakuje, ponieważ nie powiedziałeś nam aplikacji. Przekaż nam szkic aplikacji, a odpowiedzi będą lepiej dopasowane do Twojego kontekstu.

  5. Dlaczego, u licha, myślisz, że coś szybciej istnieje? Nie usprawiedliwiłeś swojego przeczucia. To bardzo trudny problem. (Czyli znaleźć coś szybciej)

+0

Testowanie na prime to taki nudziarz, że ja całkowicie zgadzam się z jlv ... po prostu zapisz i sprawdź. W rzeczywistości powinna istnieć wolna globalna usługa sieciowa, która jest buforowana globalnie, która może dostarczyć odpowiedzi ... lub jeszcze lepiej, java powinna przechowywać wszystkie liczby pierwsze do max int w odnośniku; w świecie Docker powinien być obraz z aplikacją, która zapewnia szereg usług wokół liczb pierwszych, w tym wyszukiwanie. To po prostu taki nudziarz, aby go przetestować, a następnie szukać najbardziej wydajnej metody w dowolnym języku. – Beezer

0

Można to zrobić lepiej niż za pomocą Sieve of Atkin, ale jest to dość trudne do wdrożenia go szybko i poprawnie. Proste tłumaczenie pseudokodu Wikipedii prawdopodobnie nie jest wystarczająco dobre.

+0

Tak, próbowałem zrobić sito Atkinsa ... moja tablica zawierała nawet parzyste liczby, ale ich nie dotykałem ... było 1,5 razy wolniej niż sito eroathenes. (większość znalezionych kodów podwoiła się z mojej eroa). i oczywiście - użyłem nawet właściwości pierwiastków i powiedzmy, że wiem, że dokonuję optymalizacji ... ale wciąż jest wolniej (w tablicy są niepotrzebne bajty ... to nie powinno mieć znaczenia). – Ohad

+0

Dlaczego nie wyświetlasz również tego kodu? – Landei

+0

Bardzo szybka implementacja C od jednego z autorów artykułu opisującego to na http://cr.yp.to/primegen.html – Olathe

2

Najszybszym algorytmem dotychczasowego doświadczenia jest Sito Erathostenes z faktoryzacją koła dla 2, 3 i 5, gdzie liczby pierwotne spośród pozostałych liczb są reprezentowane jako bity w tablicy bajtów. W Javie na jednym rdzeniu mojego 3-letniego Laptopa obliczanie liczb pierwszych do 1 miliarda trwa 23 sekundy.

Przy rozkładzie na kołach Sieve of Atkin był o dwa razy wolniejszy, a ze zwykłym BitSet był o 30% szybszy.

Zobacz także this answer.

1

Zrobiłem algorytm, który może znaleźć liczby pierwsze z zakresu 2-90 000 000 przez 0,65 s na I 350M-notes, napisane w C .... musisz użyć operacji bitowych i mieć "kod" do ponownego obliczania indeksu twojej tablicy do indeksu konkretnego fragmentu, który chcesz. na przykład jeśli chcesz utworzyć fałdy liczby 2, konkretne bity będą na przykład .... 10101000 ... więc jeśli czytasz od lewej ... otrzymujesz indeks 4,6,8 ... to jest

Powiązane problemy