A leghatékonyabb kód első 10000 prímszám?

szavazat
49

Azt akarom, hogy nyomtassa ki az első 10000 prímszám. Tud valaki adjon nekem a leghatékonyabb kód? tisztázása:

  1. Nem számít, ha a kód nem hatékony n> 10000.
  2. A kód mérete nem számít.
  3. Nem lehet csak a kódba az értékeket semmilyen módon.
A kérdést 03/08/2008 06:45
a forrás felhasználó
Más nyelveken...                            


29 válasz

szavazat
41

Szita Atkin talán, amit keres, annak felső korlát futási ideje O (N / log log N).

Ha csak fut a számokat 1-több és kevesebb, mint 1 többszörösei 6, lehet, hogy még gyorsabb legyen, mint az összes prímszám fenti 3 az 1-re többszörösével hat. Ehhez én nyilatkozatot

Válaszolt 03/08/2008 07:03
a forrás felhasználó

szavazat
4

Nem hatékony egyáltalán, de akkor egy szabályos kifejezés teszteli a prímszám.

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

Ez teszteli, hogy, az álló jelsorozat k1” s, k jelentése nem elsőrendű (azaz, hogy a húr áll egy „ 1” vagy tetszőleges számú „ 1” s amely kifejezhető, mint egy n -aril termék).

Válaszolt 03/08/2008 19:52
a forrás felhasználó

szavazat
4

Azt alkalmazkodott kód megtalálható a CodeProject hozzuk létre a következő:

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 + " ");
    }
}

Tesztelés ezt én ASP.NET szerver vette a rountine kb 1 perc futni.

Válaszolt 05/08/2008 20:55
a forrás felhasználó

szavazat
35

Azt javaslom egy szitán, akár a szita Eratosthenes vagy szitán Atkin.

A szita vagy Eratosthenes talán a leginkább intuitív módszert kell találni egy listát a prímszám. Alapvetően:

  1. Írja le a számok listája 2 és bármilyen korlátot szeretne, mondjuk 1000.
  2. Vegyük az első szám, mely nem jutott ki (az első iteráció ez 2) és a határon ki az összes többszörösei azt a számot a listából.
  3. Ismételje a 2. lépést, amíg el nem éri a végén a lista. Minden a számok, amelyek nincsenek át le prím.

Természetesen vannak jó néhány optimalizálást lehet tenni, hogy ez az algoritmus gyorsabban, de ez az alapötlet.

A szita Atkin használ egy hasonló megközelítést, de sajnos nem tudom, elég róla, hogy magyarázzam el. De azt tudom, hogy az algoritmus linkelt 8 másodperc kitalálni az összes prímszám-ig 1000000000 egy ősi Pentium II-350

Szitán Eratosthenes Source Code: http://web.archive.org/web/20140705111241/http://primes.utm.edu/links/programs/sieves/Eratosthenes/C_source_code/

Szitán Atkin Source Code: http://cr.yp.to/primegen.html

Válaszolt 06/08/2008 00:49
a forrás felhasználó

szavazat
3

Szitán Eratosthenes az út, mert ez az egyszerűség és a gyorsaság. Saját végrehajtás 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 Ideje, hogy prímszám (Pentium Dual Core E2140 1,6 GHz-es, egymagos használva)

~ 4s lim = 100,000,000

Válaszolt 21/08/2008 00:45
a forrás felhasználó

szavazat
11

GateKiller , mit szólnál hozzá egy breake ifa foreachhurok? Ez lenne felgyorsítani a dolgokat sokat , mert ha így a 6 osztható 2 akkor nem kell, hogy ellenőrizze a 3. és az 5. (én szavaz a megoldás fel egyébként, ha már elég jó hírnevét :-) ...)

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 + " ");
    }
}
Válaszolt 27/08/2008 21:26
a forrás felhasználó

szavazat
7

GMP, lehetne írni a következő:

#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));
  }
}

Az én 2,33 GHz Macbook Pro, akkor végrehajtja az alábbiak szerint:

time ./a.out > /dev/null

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

Kiszámítása 1.000.000 prímszám ugyanazon laptop:

time ./a.out > /dev/null

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

GMP erősen optimalizált ilyesmit. Kivéve, ha igazán meg akarjuk érteni az algoritmusok által írásban a saját, akkor lenne tanácsos használni libgmp alatt C.

Válaszolt 29/08/2008 08:06
a forrás felhasználó

szavazat
17

Ez nem feltétlenül ellen égetve korlátozás, de jön borzasztóan közel. Miért ne programozottan letölteni ezt a listát, és nyomtassa ki, helyette?

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

Válaszolt 31/08/2008 23:20
a forrás felhasználó

szavazat
9

@Matt: log (log (10000)) jelentése ~ 2

A wikipedia cikk (amit idézett) szitán Atkin :

Ez a szitán számítja prímszám akár az N O(N/log log N)műveletek csak az N 1/2 + O (1) bit memória. Ez egy kicsit jobb, mint a szitán Eratosthenes használó O(N) műveletek és az O (N 02/01 (log log N) / log N) bit memória (AOL Atkin, DJ Bernstein, 2004) . Ezek aszimptotikus számítási bonyolultsága közé tartozik az egyszerű optimalizáció, mint a kerék faktorizációhoz felosztja a számítást a kisebb blokkok.

Mivel aszimptotikus számítási bonyolultsága mentén O(N)(a Eratosthenes) és O(N/log(log(N)))(a Atkin) nem tudjuk megmondani, (kis N=10_000), amely algoritmus végrehajtása esetén gyorsabb lesz.

Achim Flammenkamp írta szita Eratosthenes :

által idézett:

@ NUM1

Mert időközönként nagyobb körülbelül 10 ^ 9, biztosan azok számára> 10 ^ 10, szita Eratosthenes van túlteljesítette szitapróbával Atkins és Bernstein használó kiküszöbölhetetlen bináris kvadratikus formák. Lásd a papír háttér információk, valamint 5. bekezdése W. Galway Ph.D. tézis.

Ezért a 10_000szitán Eratosthenes gyorsabb lehet majd szitán Atkin.

Válaszolni OP a kód prime_sieve.c (idézi num1)

Válaszolt 06/10/2008 21:03
a forrás felhasználó

szavazat
2

Adaptálása és folytatva GateKiller , itt a végleges verzió, amit használnak.

    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;
    }

Ez alapvetően ugyanaz, de adtam a „megtörnek Sqrt” a javaslatot, és megváltoztatta egyes változók körül, hogy az illeszkedjen jobb nekem. (Dolgoztam Euler és szükséges a 10001th prime)

Válaszolt 16/02/2009 06:17
a forrás felhasználó

szavazat
2

A Szita úgy tűnik, hogy a rossz válasz. A szita megadja a prímszám -ig számos N , nem az első N prímszám. Run @Imran vagy @Andrew Szeto, és megkapod a prímszám-ig N.

A szita lehet még használható, ha próbálkozom sziták egyre nagyobb számban, amíg bejön egy bizonyos méretet a eredményhalmaz, és használhatja caching számok már kapott, de azt hiszem, ez még mindig nem gyorsabb, mint a megoldás, mint a @ Pat .

Válaszolt 19/06/2009 19:12
a forrás felhasználó

szavazat
3

Itt van egy szitán Eratosthenes hogy írtam PowerShell néhány nappal ezelőtt. Ez a paraméter azonosító száma prímszám, hogy vissza kell küldeni.

#
# 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
}
Válaszolt 07/09/2009 19:52
a forrás felhasználó

szavazat
2

A Pythonban

import gmpy
p=1
for i in range(10000):
    p=gmpy.next_prime(p)
    print p 
Válaszolt 22/02/2010 08:45
a forrás felhasználó

szavazat
0

Írtam ezt a python, ahogy elkezdtem tanulni, és ez működik tökéletesen. A 10000. elsődleges generál a kód által ugyanaz, mint említett http://primes.utm.edu/lists/small/10000.txt . Annak ellenőrzéséhez, hogy nprím-e vagy sem, oszd nmeg a számokat 2, hogy sqrt(n). Ha ezek közül bármelyik szám tartományát tökéletesen osztja nakkor nem prím.

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))
Válaszolt 27/12/2010 18:37
a forrás felhasználó

szavazat
1

Itt van a VB 2008-kódot, amely megállapítja az összes prímszám <10000000 1 perc 27 másodperc a munkámra laptop. Kihagyja a páros számok, és csak úgy néz ki, a prímszám, amelyek <a sqrt a vizsgálati szám. Ez csak célja, hogy megtalálja prímszám 0 olyan Sentinal értéket.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 
Button1.Click

    Dim TestNum As Integer
    Dim X As Integer
    Dim Z As Integer
    Dim TM As Single
    Dim TS As Single
    Dim TMS As Single
    Dim UnPrime As Boolean
    Dim Sentinal As Integer
    Button1.Text = "Thinking"
    Button1.Refresh()
    Sentinal = Val(SentinalTxt.Text)
    UnPrime = True
    Primes(0) = 2
    Primes(1) = 3
    Z = 1
    TM = TimeOfDay.Minute
    TS = TimeOfDay.Second
    TMS = TimeOfDay.Millisecond
    For TestNum = 5 To Sentinal Step 2
        Do While Primes(X) <> 0 And UnPrime And Primes(X) ^ 2 <= TestNum
            If Int(TestNum / Primes(X)) - (TestNum / Primes(X)) = 0 Then
                UnPrime = False
            End If
            X = X + 1

        Loop
        If UnPrime = True Then
            X = X + 1
            Z = Z + 1
            Primes(Z) = TestNum
        End If
        UnPrime = True
        X = 0
    Next
    Button1.Text = "Finished with " & Z
    TM = TimeOfDay.Minute - TM
    TS = TimeOfDay.Second - TS
    TMS = TimeOfDay.Millisecond - TMS
    ShowTime.Text = TM & ":" & TS & ":" & TMS
End Sub
Válaszolt 11/03/2011 03:25
a forrás felhasználó

szavazat
0

Töltök egy kis időt programot írni kiszámítása sok prímszám, és ez a kód én kiszámításához használt egy szöveges fájl, amely az első 1.000.000.000 prímszám. Ez német, de az érdekes rész a módszer calcPrimes(). A prímszám tárolják nevű tömbben Primzahlen. Azt javaslom 64bit CPU, mert a számítások a 64 bites egészek.

import java.io.*;
class Primzahlengenerator {
    long[] Primzahlen;
    int LastUnknown = 2;
    public static void main(String[] args)  {
        Primzahlengenerator Generator = new Primzahlengenerator();
        switch(args.length) {
            case 0:  //Wenn keine Argumente übergeben worden:
                Generator.printHelp(); //Hilfe ausgeben
                return; //Durchfallen verhindern
            case 1:
                try {
                    Generator.Primzahlen = new long[Integer.decode(args[0]).intValue()];
                }
                catch (NumberFormatException e) {
                    System.out.println("Das erste Argument muss eine Zahl sein, und nicht als Wort z.B. \"Tausend\", sondern in Ziffern z.B. \"1000\" ausgedrückt werden.");//Hinweis, wie man die Argumente angeben muss ausgeben
                    Generator.printHelp();                    //Generelle Hilfe ausgeben
                    return;
                }
                break;//dutchfallen verhindern

            case 2:
                switch (args[1]) {
                    case "-l":
                        System.out.println("Sie müsen auch eine Datei angeben!"); //Hilfemitteilung ausgeben
                        Generator.printHelp();                                    //Generelle Hilfe ausgeben
                        return;
                }
                break;//durchfallen verhindern
            case 3:
                try {
                    Generator.Primzahlen = new long[Integer.decode(args[0]).intValue()];
                }
                catch (NumberFormatException e) {
                    System.out.println("Das erste Argument muss eine Zahl sein, und nicht als Wort z.B. \"Tausend\", sondern in Ziffern z.B. \"1000\" ausgedrückt werden.");//Hinweis, wie man die Argumente angeben muss ausgeben
                    Generator.printHelp();                      //Generelle Hilfe ausgeben
                    return;
                }
                switch(args[1]) {
                    case "-l":
                        Generator.loadFromFile(args[2]);//Datei Namens des Inhalts von Argument 3 lesen, falls Argument 2 = "-l" ist
                        break;
                    default:
                        Generator.printHelp();
                        break;
                }
                break;
            default:
                Generator.printHelp();
                return;
        }
        Generator.calcPrims();
    }
    void printHelp() {
        System.out.println("Sie müssen als erstes Argument angeben, die wieviel ersten Primzahlen sie berechnen wollen.");   //Anleitung wie man das Programm mit Argumenten füttern muss
        System.out.println("Als zweites Argument können sie \"-l\" wählen, worauf die Datei, aus der die Primzahlen geladen werden sollen,");
        System.out.println("folgen muss. Sie muss genauso aufgebaut sein, wie eine Datei Primzahlen.txt, die durch den Aufruf \"java Primzahlengenerator 1000 > Primzahlen.txt\" entsteht.");
    }
    void loadFromFile(String File) {
        // System.out.println("Lese Datei namens: \"" + File + "\"");
        try{
            int x = 0;
            BufferedReader in = new BufferedReader(new FileReader(File));
            String line;
            while((line = in.readLine()) != null) {
                Primzahlen[x] = new Long(line).longValue();
                x++;
            }
            LastUnknown = x;
        } catch(FileNotFoundException ex) {
            System.out.println("Die angegebene Datei existiert nicht. Bitte geben sie eine existierende Datei an.");
        } catch(IOException ex) {
            System.err.println(ex);
        } catch(ArrayIndexOutOfBoundsException ex) {
            System.out.println("Die Datei enthält mehr Primzahlen als der reservierte Speicherbereich aufnehmen kann. Bitte geben sie als erstes Argument eine größere Zahl an,");
            System.out.println("damit alle in der Datei enthaltenen Primzahlen aufgenommen werden können.");
            }
        /* for(long prim : Primzahlen) {
            System.out.println("" + prim);
        } */
        //Hier soll code stehen, der von der Datei mit angegebenem Namen ( Wie diese aussieht einfach durch angeben von folgendem in cmd rausfinden:
        //java Primzahlengenerator 1000 > 1000Primzahlen.txt
        //da kommt ne textdatei, die die primzahlen enthält. mit Long.decode(String ziffern).longValue();
        //erhält man das was an der entsprechenden stelle in das array soll. die erste zeile soll in [0] , die zweite zeile in [1] und so weiter.
        //falls im arry der platz aus geht(die exception kenn ich grad nich, aber mach mal:
        //int[] foo = { 1, 2, 3};
        //int bar = foo[4];
        //dann kriegst ne exception, das ist die gleiche die man kriegt, wenn im arry der platzt aus geht.
    }
    void calcPrims() {
        int PrimzahlNummer = LastUnknown;
        // System.out.println("LAstUnknown ist: " + LastUnknown);
        Primzahlen[0] = 2;
        Primzahlen[1] = 3;
        long AktuelleZahl = Primzahlen[PrimzahlNummer - 1];
        boolean IstPrimzahl;
        // System.out.println("2");
        // System.out.println("3");
        int Limit = Primzahlen.length;
        while(PrimzahlNummer < Limit) {
            IstPrimzahl = true;
            double WurzelDerAktuellenZahl = java.lang.Math.sqrt(AktuelleZahl);
            for(int i = 1;i < PrimzahlNummer;i++) {
                if(AktuelleZahl % Primzahlen[i] == 0) {
                    IstPrimzahl = false;
                    break;
                }
                if(Primzahlen[i] > WurzelDerAktuellenZahl) break;
            }
            if(IstPrimzahl) {
                Primzahlen[PrimzahlNummer] = AktuelleZahl;
                PrimzahlNummer++;
                // System.out.println("" + AktuelleZahl);
            }
            AktuelleZahl = AktuelleZahl + 2;
        }
        for(long prim : Primzahlen) {
            System.out.println("" + prim);
        }
    }
}
Válaszolt 23/04/2012 20:46
a forrás felhasználó

szavazat
9

A Haskell, tudjuk leírni szinte szóról szóra a matematikai meghatározását szitán Eratosthenes „ prím természetes számok 1-nél nélkül összetett szám, ahol kompozitok talált felsorolás minden Prime többszöröse ”:

primes = 2 : minus [3..] (foldr (\p r-> p*p : union [p*p+p, p*p+2*p..] r) 
                                [] primes)

primes !! 10000 a közel azonnali.

Irodalom:


A fenti kód könnyen csípett bele dolgozik odds csak primes = 2:3:minus [5,7..] (foldr (\p r -> p*p : union [p*p+2*p, p*p+4*p..] r) [] (tail primes)). Időbonyolultsága sokat javult (csak egy log faktor feletti optimális) hajtásával egy fa-szerű szerkezet, és a tér komplexitás drasztikusan javítani a többlépcsős prímszám termelés , a

primes = 2 : _Y ( (3:) . sieve 5 . _U . map (\p-> [p*p, p*p+2*p..]) )
  where
    _Y g = g (_Y g)                        -- non-sharing fixpoint combinator
    _U ((x:xs):t) = x : (union xs . _U . pairs) t       -- ~= nub.sort.concat
    pairs    (xs:ys:t)  = union xs ys : pairs t
    sieve k s@(x:xs) | k < x      = k : sieve (k+2) s   -- ~= [k,k+2..]\\s,
                     | otherwise  =     sieve (k+2) xs  --   when s⊂[k,k+2..]

(A Haskell zárójelben használják csoportosulás, a függvényhívás jelentette pusztán egymás mellett, (:)egy hátránya üzemeltető listákat, és (.)egy funkcionális készítmény üzemeltető: (f . g) x = (\y-> f (g y)) x = f (g x)).

Válaszolt 24/04/2012 17:30
a forrás felhasználó

szavazat
-1
using System;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            int n, i = 3, j, c;
            Console.WriteLine("Please enter your integer: ");
            n = Convert.ToInt32(Console.ReadLine());
            if (n >= 1)
            {
                Console.WriteLine("First " + n + " Prime Numbers are");
                Console.WriteLine("2");
            }
            for(j=2;j<=n;)
            {
                for(c=2;c<=i-1;c++)
                {
                    if(i%c==0)
                        break;
                }
                    if(c==i)
                    {
                        Console.WriteLine(i);
                        j++;
                    }
                    i++;                                
            }
            Console.Read();
        }
    }
}
Válaszolt 08/05/2012 05:15
a forrás felhasználó

szavazat
1

A következő Mathcad kód számított első millió prímszám 3 perc alatt.

Tartsuk szem előtt, hogy ez lenne a lebegőpontos megduplázza az összes számot, és alapvetően értelmezni. Remélem, hogy a szintaxis egyértelmű.

írja kép leírása itt

Válaszolt 02/03/2014 02:15
a forrás felhasználó

szavazat
1

Itt van egy C ++ oldat, egy formája SOE:

#include <iostream>
#include <deque>

typedef std::deque<int> mydeque;

void my_insert( mydeque & factors, int factor ) {
    int where = factor, count = factors.size();
    while( where < count && factors[where] ) where += factor;
    if( where >= count ) factors.resize( where + 1 );
    factors[ where ] = factor;
}

int main() {
    mydeque primes;
    mydeque factors;
    int a_prime = 3, a_square_prime = 9, maybe_prime = 3;
    int cnt = 2;
    factors.resize(3);
    std::cout << "2 3 ";

    while( cnt < 10000 ) {
        int factor = factors.front();
        maybe_prime += 2;
        if( factor ) {
            my_insert( factors, factor );
        } else if( maybe_prime < a_square_prime ) {
            std::cout << maybe_prime << " ";
            primes.push_back( maybe_prime );
            ++cnt;
        } else {
            my_insert( factors, a_prime );
            a_prime = primes.front();
            primes.pop_front();
            a_square_prime = a_prime * a_prime;
        }
        factors.pop_front();
    }

    std::cout << std::endl;
    return 0;
}

Megjegyzendő, hogy ez a verzió a Szita tudja számítani prímszám végtelenségig.

Szintén fontos megjegyezni, az STL dequevesz O(1)idő, hogy végre push_back, pop_frontés véletlen hozzáférés bár indexelés.

A resizeműtét időtartama O(n)időben, ahol nvan az elemek száma bővül. Mivel a hogyan használjuk ezt a funkciót, tudjuk kezelni ez egy kis állandó.

A test a whilehurok my_insertkerül végrehajtásra O(log log n)időkben, ahol negyenlő a változó maybe_prime. Ez azért van, mert a feltétel kifejezése whileértékelni fogja, hogy igaz, ha minden egyes elsődleges tényező maybe_prime. Lásd: „ Divisor funkció ” a Wikipédián.

Megszorozzuk hányszor my_inserthívják, azt mutatja, hogy meg kell venni O(n log log n)az ideje, hogy felsorolni nprímszám ... ami nem meglepő, időbonyolultsága amely a szitán Eratosthenes állítólag van.

Míg azonban ez a kód van hatékony, ez nem a leghatékonyabb ... azt javasoljuk, egy speciális könyvtár prímszám generáció, mint a primesieve . Az igazán hatékony, jól optimalizált megoldás, lesz több kódot, mint bárki akar írja be StackOverflow.

Válaszolt 16/04/2016 18:33
a forrás felhasználó

szavazat
2

A deque szita algoritmus által említett BenGoldberg megérdemel egy közelebbi pillantást, nem csak azért, mert nagyon elegáns, de azért is, mert néha hasznos lehet a gyakorlatban (ellentétben a szitán Atkin, ami tisztán akadémiai gyakorlat).

Az alapgondolata az deque szita algoritmus, hogy egy kis, csúszó szitán, hogy csak a nagy ahhoz, hogy benne legalább egy külön több az egyes jelenleg „aktív” elsődleges tényező - vagyis azokat, prímszám, amelynek négyzete nem haladja meg a legkisebb számot jelenleg képviseli a mozgó szitán. A másik különbség, hogy a SOE, hogy a deque szita tárolja az aktuális tényezőt a résekbe kompozitok, nem logikai értékek.

Az algoritmus kiterjeszti a méret a szitán ablak szükség, ami meglehetősen egyenletes teljesítményt széles tartományban, amíg a szitán kezd meghaladja a kapacitást, a CPU L1 cache észrevehetően. Az utolsó elsődleges, hogy illik teljesen a 25237523 (a 1,579,791st prime), amely egy durva becslési adat az ésszerű működési tartománya az algoritmust.

Az algoritmus meglehetősen egyszerű és robosztus, és ez még akkor is elérhető, mint egy sokkal szélesebb körű, mint egy több részből szitán Eratosthenes. Az utóbbi egy sokkal gyorsabb, mint a hosszú annak szitán illeszkedik teljesen a cache, azaz legfeljebb 2 ^ 16 odds csak szita bájt méretű bools. Ezután a teljesítménye csökken, és több, bár mindig is lényegesen gyorsabb, mint a deque ellenére hátrány (legalábbis összeállított nyelvek, mint a C / C ++, Pascal vagy Java / C #).

Itt van egy teszi a deque szita algoritmus C #, mert én meg, hogy a nyelv - annak ellenére, hogy sok hibát - sokkal praktikusabb prototípus algoritmusok és kísérletezés, mint a páratlanul nehézkes és pedáns C ++. (Megjegyzést az: Én az ingyenes LINQPad , amely lehetővé teszi a zuhanásra, anélkül, hogy a bepiszkolódás a projektek létrehozása, makefiles, könyvtárakat, vagy miegymás, és ez ad nekem ugyanolyan fokú interaktivitást a python prompt).

C # nem rendelkezik kifejezett deque típusú, hanem a sima List<int>működik elég jól bizonyítja az algoritmust.

Megjegyzés: ez a verzió nem használ deque a prímet, mert egyszerűen nincs értelme elsül sqrt (n) n-ből prímszám. Mire jó lenne eltávolítani 100 prímszám, és hagyja 9900? Így legalább az összes prímszám gyűjteni egy takaros vektor, készen áll a további feldolgozásra.

static List<int> deque_sieve (int n = 10000)
{
    Trace.Assert(n >= 3);

    var primes = new List<int>()  {  2, 3  };
    var sieve = new List<int>()  {  0, 0, 0  };

    for (int sieve_base = 5, current_prime_index = 1, current_prime_squared = 9; ; )
    {
        int base_factor = sieve[0];

        if (base_factor != 0)
        {
            // the sieve base has a non-trivial factor - put that factor back into circulation
            mark_next_unmarked_multiple(sieve, base_factor);
        }
        else if (sieve_base < current_prime_squared)  // no non-trivial factor -> found a non-composite
        {
            primes.Add(sieve_base);

            if (primes.Count == n)
                return primes;
        }
        else // sieve_base == current_prime_squared
        {
            // bring the current prime into circulation by injecting it into the sieve ...
            mark_next_unmarked_multiple(sieve, primes[current_prime_index]);

            // ... and elect a new current prime
            current_prime_squared = square(primes[++current_prime_index]);
        }

        // slide the sieve one step forward
        sieve.RemoveAt(0);  sieve_base += 2;
    }
}

Íme a két segítő funkciók:

static void mark_next_unmarked_multiple (List<int> sieve, int prime)
{
    int i = prime, e = sieve.Count;

    while (i < e && sieve[i] != 0)
        i += prime;

    for ( ; e <= i; ++e)  // no List<>.Resize()...
        sieve.Add(0);

    sieve[i] = prime;
}

static int square (int n)
{
    return n * n;
}

Talán a legegyszerűbb módja a megértés az algoritmus elképzelni, mint egy különleges szegmentált szitán Eratosthenes a szegmens mérete 1 kíséretében túlfolyó területen, ahol a prímszám jönnek pihenni, amikor lőni át a végén a szegmensben. Kivéve, hogy az egyes sejtek a szegmens (aka sieve[0]) már szitált mikor érünk rá, mert ez van elgázolta volt, míg egy részét a túlfolyó területen.

A szám képviseli sieve[0]tartják sieve_base, bár sieve_frontvagy window_baselenne egy jó nevek, amelyekkel párhuzamba Ben kódja vagy megvalósításai szegmentált / ablakos rostán.

Ha sieve[0]tartalmaz egy nem zéró értéke, akkor az érték egy tényező sieve_base, amely így ismeri fel kompozit. Mivel a sejthez 0 többszöröse e tényező könnyű kiszámítani a következő hop, ami egyszerűen 0 plusz ezt a tényezőt. Amennyiben a cellában elfoglalható már egy másik tényező, akkor egyszerűen csak adjuk hozzá a tényező újra, és így tovább, amíg nem találunk többszöröse a tényező, ahol nincs más tényező jelenleg parkol (kiterjesztése a szitán, ha szükséges). Ez azt is jelenti, hogy nincs szükség tárolására a munka jelenlegi ellensúlyozza a különböző prímszám egyik szegmens a másikra, mint a szokásos szegmentált szitán. Amikor találunk egy tényező sieve[0], a jelenlegi Szerződés offset 0.

A jelenlegi elsődleges kerül szóba a következő módon. A prime csak akkor válhat a jelenlegi után saját előfordulása a falon (azaz, ha azt érzékeli, hogy elsődleges, mert nincs jelölve faktor), és az is marad addig, amíg az pontosan abban a pillanatban, hogy sieve[0]eléri a téren. Minden kisebb többszöröse ennek elsődleges kell töröltek tevékenysége miatt kisebb prímszám, mint egy normális SOE. De sem a kisebb prímszám sztrájk le a térre, hiszen az egyetlen tényező, a tér az elsődleges magát, és ez még nem a forgalomban ezen a ponton. Ez megmagyarázza, hogy a hozott intézkedések az algoritmus esetén sieve_base == current_prime_squared(ami azt jelenti sieve[0] == 0, az úton).

Most a helyzet sieve[0] == 0 && sieve_base < current_prime_squaredkönnyen magyarázható: ez azt jelenti, hogy sieve_basenem lehet több bármelyik prímszám kisebb, mint a jelenlegi elsődleges, vagy pedig ez lett jelölve összetett. Azt nem lehet nagyobb többszöröse a jelenlegi elsődleges sem, mivel annak értéke kisebb, mint a jelenlegi elsődleges téren. Ezért kell egy új prímszám.

Az algoritmus nyilvánvalóan ihlette szitán Eratosthenes, de ugyanilyen nyilvánvalóan nagyon különböző. Szita Eratosthenes nyeri kiváló sebesség egyszerűsége annak elemi műveletek: egyetlen index összeadás és egy tároló minden lépését a művelet minden, mégis a hosszabb időre.

Itt van egy egyszerű, nem szegmentált szitán Eratosthenes amit általában használni szitálással tényező prím a ushort tartományban, azaz legfeljebb 2 ^ 16. Mert ezt a bejegyzést, amit módosítani, hogy működjön túl 2 ^ 16 helyettesítve intazushort

static List<int> small_odd_primes_up_to (int n)
{
    var result = new List<int>();

    if (n < 3)
        return result;

    int sqrt_n_halved = (int)(Math.Sqrt(n) - 1) >> 1, max_bit = (n - 1) >> 1;
    var odd_composite = new bool[max_bit + 1];

    for (int i = 3 >> 1; i <= sqrt_n_halved; ++i)
        if (!odd_composite[i])
            for (int p = (i << 1) + 1, j = p * p >> 1; j <= max_bit; j += p)
                odd_composite[j] = true;

    result.Add(3);  // needs to be handled separately because of the mod 3 wheel

    // read out the sieved primes
    for (int i = 5 >> 1, d = 1; i <= max_bit; i += d, d ^= 3)
        if (!odd_composite[i])
            result.Add((i << 1) + 1);

    return result;
}

Amikor szitáljuk az első 10000 telíti tipikus L1 cache 32 KiByte túllépik, de a funkció még mindig nagyon gyors (frakció egy milliszekundumos még C #).

Ha összehasonlítjuk ezt a kódot a deque szitán, akkor könnyen belátható, hogy a műveleteket a deque szitán sokkal bonyolultabb, és nem tudja hatékonyan amortizálja a fej-, mert mindig azt a lehető legrövidebb szakaszon kereszteződések-off egy sorban (pontosan egyetlen átkelőhely-off után ugró összes többszörösei, hogy már át le már).

Megjegyzés: a C # kódot használ intahelyett uint, mert újabb fordítóprogramok a szokás generáló kifogásolható kódot uint, valószínűleg azért, hogy álljon az emberek felé, aláírt egész ... A C ++ változatát a fenti kódot használtam unsignedaz egész, természetesen; A benchmark kellett lennie C ++, mert azt akartam, kell alapulnia állítólag megfelelő deque típusú ( std::deque<unsigned>nem volt semmi teljesítmény erősítés segítségével unsigned short). Itt vannak a számok az én Haswell laptop (VC ++ 2015 / x64):

deque vs simple: 1.802 ms vs 0.182 ms
deque vs simple: 1.836 ms vs 0.170 ms 
deque vs simple: 1.729 ms vs 0.173 ms

Megjegyzés: a C # idők nagyjából pontosan kétszerese a C ++ időzítést, ami elég jó a C # és ez azt mutatja, hogy List<int>nem nehézkes, még ha visszaélnek vele deque.

Az egyszerű szita kódot mindig fúj a deque ki a vízből, bár már jelen van túl a normál üzemi tartományban (L1 cache mérete meghaladta a 50% -ot, az ezzel együtt járó cache rángatózás). Az uralkodó része itt a kiolvasása a szitált prímszám, és ez nem befolyásolja lényegesen a cache probléma. Mindenesetre a funkció célja az volt, szitálással tényezők tényezők, azaz a 0. szintű egy 3 szintes szitán hierarchia, és általában azt, hogy visszatérjen csak néhány száz tényezők, vagy egy alacsony ezer. Ezért az egyszerűség.

Teljesítmény javítható lenne több, mint egy nagyságrenddel segítségével szegmentált szitán, és optimalizálja a kódot kivonásához szitált prímszám (lépcsős mod 3 teríteni kétszer, vagy mod 15 teríteni egyszer), és még nagyobb teljesítményt lehet kiszorulnak a a kód segítségével a mod 16 vagy mod 30 kerék minden paszomány (azaz teljes ietekercselése minden maradék). Valami ilyesmi magyarázata a válaszom Find prime pozícionált prímszám át a Code Review, ahol egy hasonló probléma volt szó. De nehéz, hogy a pont javításában ezredmásodpercnél alkalommal egy egyszeri feladat ...

Ahhoz, hogy a dolgok egy kicsit a szempontból, itt a C ++ időzítést szitáljuk legfeljebb 100.000.000:

deque vs simple: 1895.521 ms vs 432.763 ms
deque vs simple: 1847.594 ms vs 429.766 ms
deque vs simple: 1859.462 ms vs 430.625 ms

Ezzel szemben egy szegmentált szitán C # néhány harangok és a síp ugyanazt a feladatot 95 ms (nem C ++ időzítések rendelkezésre, mivel én kódot kihívások csak C # pillanatában).

A dolgok tűnhet határozottan más interpretált nyelv, mint a Python, ahol minden művelet magas költségeket és a tolmács overhead törpék minden különbségek miatt jósolt vs. mispredicted ágak vagy al-ciklus ops (eltolódás, felül) vs. többciklusú ops (szorzás , és talán még osztás). Ez van kötve, hogy rontja az egyszerűség előnye szita Eratosthenes, és ez teszi a deque megoldás egy kicsit vonzóbb.

Emellett számos, a időzítések által bejelentett többi válaszadó ebben a témában valószínűleg uralja kiadási időt . Ez egy teljesen más háborúban, ahol a fő fegyver egy egyszerű osztály, mint ez:

class CCWriter
{
    const int SPACE_RESERVE = 11;  // UInt31 + '\n'

    public static System.IO.Stream BaseStream;
    static byte[] m_buffer = new byte[1 << 16];  // need 55k..60k for a maximum-size range
    static int m_write_pos = 0;
    public static long BytesWritten = 0;         // for statistics

    internal static ushort[] m_double_digit_lookup = create_double_digit_lookup();

    internal static ushort[] create_double_digit_lookup ()
    {
        var lookup = new ushort[100];

        for (int lo = 0; lo < 10; ++lo)
            for (int hi = 0; hi < 10; ++hi)
                lookup[hi * 10 + lo] = (ushort)(0x3030 + (hi << 8) + lo);

        return lookup;
    }

    public static void Flush ()
    {
        if (BaseStream != null && m_write_pos > 0)
            BaseStream.Write(m_buffer, 0, m_write_pos);

        BytesWritten += m_write_pos;
        m_write_pos = 0;
    }

    public static void WriteLine ()
    {
        if (m_buffer.Length - m_write_pos < 1)
            Flush();

        m_buffer[m_write_pos++] = (byte)'\n';
    }

    public static void WriteLinesSorted (int[] values, int count)
    {
        int digits = 1, max_value = 9;

        for (int i = 0; i < count; ++i)
        {
            int x = values[i];

            if (m_buffer.Length - m_write_pos < SPACE_RESERVE)
                Flush();

            while (x > max_value)
                if (++digits < 10)
                    max_value = max_value * 10 + 9;
                else
                    max_value = int.MaxValue;               

            int n = x, p = m_write_pos + digits, e = p + 1;

            m_buffer[p] = (byte)'\n';

            while (n >= 10)
            {
                int q = n / 100, w = m_double_digit_lookup[n - q * 100];
                n = q;
                m_buffer[--p] = (byte)w;
                m_buffer[--p] = (byte)(w >> 8);
            }

            if (n != 0 || x == 0)
                m_buffer[--p] = (byte)((byte)'0' + n);

            m_write_pos = e;
        }
    }
}

Ez kevesebb, mint 1 ms írásban 10000 (rendezve) számokat. Ez egy statikus osztály, mert annak célja a szöveges felvétel belefér beadványok, minimális zaj és a nulla fölött.

Általában azt találta, hogy sokkal gyorsabb, ha fókuszált munkát a teljes tételt, vagyis szitán egy bizonyos tartományban, majd csomagolja az összes prímszám egy vektor / tömb, majd robbanás ki az egész tömböt, majd szita a következő tartományban, és így tovább, helyett vegyülnek össze mindent. Miután különböző funkciók összpontosítottak konkrét feladatokat is megkönnyíti, hogy keverheted, lehetővé teszi az újrahasználat, és ez megkönnyíti a fejlesztés / tesztelés.

Válaszolt 19/04/2016 17:07
a forrás felhasználó

szavazat
1

Segítségével szitán Eratosthenes, számítás meglehetősen gyorsabb összehasonlítani „ismert széles” prímszámok algoritmus.

Segítségével pszeudokódját belőle a wiki ( https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes ), azt kell tudnia, hogy a megoldást a C #.

/// Get non-negative prime numbers until n using Sieve of Eratosthenes.
public int[] GetPrimes(int n) {
    if (n <= 1) {
        return new int[] { };
    }

    var mark = new bool[n];
    for(var i = 2; i < n; i++) {
        mark[i] = true;
    }

    for (var i = 2; i < Math.Sqrt(n); i++) {
        if (mark[i]) {
            for (var j = (i * i); j < n; j += i) {
                mark[j] = false;
            }
        }
    }

    var primes = new List<int>();
    for(var i = 3; i < n; i++) {
        if (mark[i]) {
            primes.Add(i);
        }
    }

    return primes.ToArray();
}

GetPrimes (100000000) veszi 2s és 330ms.

Megjegyzés : Érték eltérőek lehetnek attól függ Hardver specifikáció.

Válaszolt 12/05/2016 03:40
a forrás felhasználó

szavazat
0

Én már dolgozom find prímszám körülbelül egy év. Ez az, amit találtam, hogy a leggyorsabb:

import static java.lang.Math.sqrt;
import java.io.PrintWriter;
import java.io.File;
public class finder {
    public static void main(String[] args) {
        primelist primes = new primelist();
        primes.insert(3);
        primes.insert(5);
        File file = new File("C:/Users/Richard/Desktop/directory/file0024.txt");
        file.getParentFile().mkdirs();
        long time = System.nanoTime();
        try{
            PrintWriter printWriter = new PrintWriter ("file0024.txt"); 
            int linenum = 0;
            printWriter.print("2");
            printWriter.print (" , ");
            printWriter.print("3");
            printWriter.print (" , ");
            int up;
            int down;           
            for(int i =1; i<357913941;i++){//
                if(linenum%10000==0){
                    printWriter.println ("");
                    linenum++;
                }
                down = i*6-1;
                if(primes.check(down)){
                    primes.insert(down);
                    //System.out.println(i*6-1);
                    printWriter.print ( down );
                    printWriter.print (" , ");
                    linenum++;  
                }
                up = i*6+1;
                if(primes.check(up)){
                    primes.insert(up);
                    //System.out.println(i*6+1);
                    printWriter.print ( up );
                    printWriter.print (" , ");
                    linenum++;  
                }
            }
            printWriter.println ("Time to execute");
            printWriter.println (System.nanoTime()-time);
            //System.out.println(primes.length);
            printWriter.close ();
        }catch(Exception e){}
    } 
}
class node{
    node next;
    int x;
    public node (){
        node next;
        x = 3;
    }
    public node(int z) {
        node next;
        x = z;
    }
}
class primelist{
    node first;
    int length =0;
    node current;
    public void insert(int x){
        node y = new node(x);
        if(current == null){
            current = y;
            first = y;
        }else{
            current.next = y;
            current = y;
        }
        length++;
    }
    public boolean check(int x){
        int p = (int)sqrt(x);
        node y = first;
        for(int i = 0;i<length;i++){
            if(y.x>p){
                return true;
            }else if(x%y.x ==0){
                return false;
            }
            y = y.next;
        }
        return true;
    }
}

1902465190909 nano másodpercet kap a 2147483629 kezdődő 2.

Válaszolt 14/08/2016 00:20
a forrás felhasználó

szavazat
0

Itt van a kód, amely először is megállapítja 10.000 prímszám 0,049655 mp én laptop, először 1.000.000 prímszám alatt 6 másodperc, és az első 2.000.000 15 másodperc alatt
egy kis magyarázatot. Ez a módszer 2 technikákat találni prímszám

  1. Először minden nem prímszám egy összetett többszörösei prímszámok így ez a kód teszt elosztjuk a vizsgálati szám kisebb prímszám helyett tetszőleges számú, ez csökkenti számítás atleast 10 alkalommal 4 jegyű számot, és még inkább a egy nagyobb szám
  2. másrészt mellett elosztjuk elsődleges, csak oszt prímszámok kisebb, vagy egyenlő a gyökér a szám tesztelt tovább csökkentve a számítások jelentősen, ez működik, mert olyan szám, amely nagyobb, mint gyökér a szám lesz a párja szám kisebbnek kell lennie, mint a gyökér a szám, de mivel az általunk tesztelt minden szám kisebb, mint a gyökér már, ezért nem kell bajlódnia a szám nagyobb, mint a gyökér a szám tesztelnek.

Minta kimenet első 10.000 prímszám
https://drive.google.com/open?id=0B2QYXBiLI-lZMUpCNFhZeUphck0 https://drive.google.com/open?id=0B2QYXBiLI-lZbmRtTkZETnp6Ykk

Itt a kód C nyelven, be 1, majd 10,000 kinyomtatni az első 10.000 prímszám.
Edit: Elfelejtettem ez tartalmazza matematikai könyvtár, ha a Windows és a Visual Studio, mint legyen finom, de a linux meg kell lefordítani a kódot használja -lm érv vagy a kód nem működik
Példa: gcc -o -Wall „% e " "% f" -lm

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <limits.h>

/* Finding prime numbers */
int main()
{   
    //pre-phase
    char d,w;
    int l,o;
    printf("  1. Find first n number of prime numbers or Find all prime numbers smaller than n ?\n"); // this question helps in setting the limits on m or n value i.e l or o 
    printf("     Enter 1 or 2 to get anwser of first or second question\n");
    // decision making
    do
    {
        printf("  -->");
        scanf("%c",&d);
        while ((w=getchar()) != '\n' && w != EOF);
        if ( d == '1')
        {
            printf("\n  2. Enter the target no. of primes you will like to find from 3 to 2,000,000 range\n  -->");
            scanf("%10d",&l);
            o=INT_MAX;
            printf("  Here we go!\n\n");
            break;
        }
        else if ( d == '2' )
        {
            printf("\n  2.Enter the limit under which to find prime numbers from 5 to 2,000,000 range\n  -->");
            scanf("%10d",&o);
            l=o/log(o)*1.25;
            printf("  Here we go!\n\n");
            break;
        }
        else printf("\n  Try again\n");
    }while ( d != '1' || d != '2' );

    clock_t start, end;
    double cpu_time_used;
    start = clock(); /* starting the clock for time keeping */

    // main program starts here
    int i,j,c,m,n; /* i ,j , c and m are all prime array 'p' variables and n is the number that is being tested */
    int s,x;

    int p[ l ]; /* p is the array for storing prime numbers and l sets the array size, l was initialized in pre-phase */
    p[1]=2;
    p[2]=3;
    p[3]=5;
    printf("%10dst:%10d\n%10dnd:%10d\n%10drd:%10d\n",1,p[1],2,p[2],3,p[3]); // first three prime are set
    for ( i=4;i<=l;++i ) /* this loop sets all the prime numbers greater than 5 in the p array to 0 */
        p[i]=0;

    n=6; /* prime number testing begins with number 6 but this can lowered if you wish but you must remember to update other variables too */
    s=sqrt(n); /* 's' does two things it stores the root value so that program does not have to calaculate it again and again and also it stores it in integer form instead of float*/
    x=2; /* 'x' is the biggest prime number that is smaller or equal to root of the number 'n' being tested */

    /* j ,x and c are related in this way, p[j] <= prime number x <= p[c] */

    // the main loop begins here
    for ( m=4,j=1,c=2; m<=l && n <= o;)
    /* this condition checks if all the first 'l' numbers of primes are found or n does not exceed the set limit o */
    {
            // this will divide n by prime number in p[j] and tries to rule out non-primes
            if ( n%p[j]==0 )
            {
                /* these steps execute if the number n is found to be non-prime */

                ++n; /* this increases n by 1 and therefore sets the next number 'n' to be tested */
                s=sqrt(n); /* this calaulates and stores in 's' the new root of number 'n' */
                if ( p[c] <= s && p[c] != x ) /* 'The Magic Setting' tests the next prime number candidate p[c] and if passed it updates the prime number x */
                {
                    x=p[c];
                    ++c;
                }
                j=1;
                /* these steps sets the next number n to be tested and finds the next prime number x if possible for the new number 'n' and also resets j to 1 for the new cycle */
                continue; /* and this restarts the loop for the new cycle */
            }
            // confirmation test for the prime number candidate n
            else if ( n%p[j]!=0 && p[j]==x )
            {
                /* these steps execute if the number is found to be prime */
                p[m]=n;
                printf("%10dth:%10d\n",m,p[m]);
                ++n;
                s = sqrt(n);
                ++m;
                j=1;
                /* these steps stores and prints the new prime number and moves the 'm' counter up and also sets the next number n to be tested and also resets j to 1 for the new cycle */
                continue; /* and this restarts the loop */
                /* the next number which will be a even and non-prime will trigger the magic setting in the next cycle and therfore we do not have to add another magic setting here*/
            }
            ++j; /* increases p[j] to next prime number in the array for the next cycle testing of the number 'n' */
            // if the cycle reaches this point that means the number 'n' was neither divisible by p[j] nor was it a prime number
            // and therfore it will test the same number 'n' again in the next cycle with a bigger prime number
    }
    // the loops ends
    printf("  All done !!\n");
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("  Time taken : %lf sec\n",cpu_time_used);
}
Válaszolt 06/05/2017 11:48
a forrás felhasználó

szavazat
0

Itt a kód, amit tett:


enter code here
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;


int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT*/   

unsigned long int n;

int prime(unsigned long int);

scanf("%ld",&n);

unsigned long int val;

for(unsigned long int i=0;i<n;i++)
{
    int flag=0;

    scanf("%ld",&val);

    flag=prime(val);

    if(flag==1)
        printf("yes\n");

    else
        printf("no\n");
}

return 0;

}

int prime(unsigned long int n)
{

if(n==2) return 1;

else if (n == 1||n%2==0)  return 0;

for (unsigned long int i=3; i<=sqrt(n); i+=2)
    if (n%i == 0)
        return 0;

return 1;
}
Válaszolt 20/01/2018 15:50
a forrás felhasználó

szavazat
0

A Array.prototype.find () metódust Javascript. 2214.486 ms

function isPrime (number) {

  function prime(element) {
    let start = 2;
    while (start <= Math.sqrt(element)) {
      if (element % start++ < 1) {
        return false;
      }
    }
    return element > 1;
  }

  return [number].find(prime)

}

function logPrimes (n) {

  let count = 0
  let nth = n

  let i = 0
  while (count < nth) {
    if (isPrime(i)) {
      count++
      console.log('i', i) //NOTE: If this line is ommited time to find 10,000th prime is 121.157ms
      if (count === nth) {
        console.log('while i', i)
        console.log('count', count)
      }
    }
    i++
  }

}

console.time(logPrimes)

logPrimes(10000)

console.timeEnd(logPrimes) // 2214.486ms
Válaszolt 09/06/2018 21:49
a forrás felhasználó

szavazat
0

Tudok adni néhány tippet, akkor azt végrehajtani.

  1. Minden egyes számhoz kap a fele ezt a számot. Pl ellenőrzésére 21, csak így a fennmaradó elosztjuk azt tartományban 2-10.
  2. Ha a páratlan szám, csak oszd meg páratlan szám, és fordítva. Mint például a 21, osszuk 3, 5, 7, 9 csak.

Leghatékonyabb módszer felkeltem, hogy eddig.

Válaszolt 29/07/2018 19:25
a forrás felhasználó

szavazat
0

Mivel azt szeretnénk, először 10000 prímszám csak ahelyett, kódolás komplex algoritmus én javaslom a következő

boolean isPrime(int n){
//even but is prime
    if(n==2)
        return true;
//even numbers filtered already 
    if(n==0 || n==1 || n%2==0)
        return false;

// loop for checking only odd factors
// i*i <= n  (same as i<=sqrt(n), avoiding floating point calculations)
    for(int i=3 ; i*i <=n ; i+=2){
    // if any odd factor divides n then its not a prime!
        if(n%i==0)
            return false;
    }
// its prime now
    return true;
}

Most hívás elsődleges ahogy szükség van rá

for(int i=1 ; i<=1000 ; i++){
    if(isPrime(i)){
       //do something
    }
}
Válaszolt 16/11/2018 05:34
a forrás felhasználó

szavazat
0

Ez egy régi kérdés, de van itt valami, mindenki hiányzik ...

Mert ez a kis prímszám, tárgyalás osztály nem hogy lassú ... már csak 25 prímszám alatt 100. Ilyen kevés prímszám a vizsgálat, és az ilyen kis prímszám, akkor húzza ki egy ügyes trükk!

Ha a értéke relatív prím, hogy b, akkor lnko AB = 1 relatív prím. Fun szó. Azt jelenti, hogy nem osztja minden elsődleges tényező . Mi lehet tehát tesztelni oszthatóság több prímszám egy GCD hívást. Mennyi? Nos, a termék az első 15 prímszám kevesebb, mint 2 ^ 64. A terméket a következő 10 is kevesebb, mint 2 ^ 64. Ez minden, amire szükségünk van a 25. De vajon megéri?

Lássuk:

check x = null $ filter ((==0) . (x `mod`)) $ [<primes up to 101>]
Prelude> length $ filter check [101,103..85600]
>>> 9975
(0.30 secs, 125,865,152 bytes

a = 16294579238595022365 :: Word64
b = 14290787196698157718
pre = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
primes = (pre ++) $ filter ((==1) . gcd a) $ filter ((==1) . gcd b) [99,101..85600]
main = print $ length primes

Prelude> main
>>> 10000
(0.05 secs, 36,387,520 bytes)

A 6-szeres javulás van.

( lengthKényszeríteni a listát kell kiszámítani. Alapértelmezés Haskell kiírja a dolgokat 1 Unicode karakter egy időben, és így valójában a nyomtatás a lista sem dominálnak az időt, vagy uralni az összeg a ténylegesen használt kód.)

Természetesen ez fut GHCi - egy repl futó értelmezett kód - egy régi laptop, és nem értelmező bármelyik ezeket a számokat int64s vagy akár BigInts, és nem is fog akkor is, ha kéred, hogy (jól lehet kényszeríteni, , de ez csúnya és nem sokat segít). Ez értelmezése minden egyes szám van például generalizált Integer-szerű dolog, hogy lehet specializált néhány sajátos típusát, szótározó, és végighalad a láncolt lista (amely nem fuzionált el itt ez nem lefordított) 3-szor. Érdekes, hogy kézzel kombinálva a két szűrő valójában lelassítja a REPL.

Nézzük lefordítani:

...\Haskell\8.6\Testbed>Primes.exe +RTS -s
10000
606,280 bytes allocated in the heap
Total   time    0.000s  (  0.004s elapsed)

Az RTS jelentést, mert a Windows. Néhány sor vágott, mert nem releváns - voltak más GC adatokat ad, vagy csak egy része a végrehajtás, és együtt adja ki 0.004s (vagy kevesebb). Ez szintén nem állandó összecsukható, mert Haskell valójában nem sokat adott. Ha állandó szeres magunkat ( main = print 10000), megkapjuk drámaian kisebb felosztás:

...Haskell\8.6\Testbed>Primes.exe +RTS -s
10000
47,688 bytes allocated in the heap
Total   time    0.000s  (  0.001s elapsed)

Szó csak annyi, hogy töltse be a futási, majd fedezze nincs semmi köze, de nyomtatásához és kilép. Adjunk hozzá kerék faktorizációs:

wheel = scanl (+) 7 $ cycle [4, 2, 4, 2, 4, 6, 2, 6]
primes = (pre ++) $ filter ((==1) . gcd a) $ filter ((==1) . gcd b) $ takeWhile (<85600) wheel

Total   time    0.000s  (  0.003s elapsed)

Vágjuk le körülbelül 1/3-képest a hivatkozás main = print 10000, de határozottan hely több optimalizálás. Ez valójában megállt, hogy végre egy GC ott például, míg a csípés ne legyen semmilyen kupac használatát. Valamilyen oknál fogva, összeállítása profilba itt valóban csökkenti a futási le 2 milliszekundum:

Tue Nov 12 21:13 2019 Time and Allocation Profiling Report  (Final)

   Primes.exe +RTS -p -RTS

total time  =        0.00 secs   (2 ticks @ 1000 us, 1 processor)
total alloc =     967,120 bytes  (excludes profiling overheads)

Megyek, hogy elhagyja ezt mint most, biztos vagyok benne, véletlenszerű jitter kezd dominálnak.

Válaszolt 13/11/2019 05:49
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more