Primtal på hjernen...

Tags:    c++

<< < 123 > >>
Jeg har sat min computer og mit uforlignelige intellekt på prøve. ;-)

Skriv et program i c++, der udregner primtal.
Så mange som muligt, så hurtigt som muligt.
De omtale tal skal skrives til en fil på harddisken ikke på skærmen.
Gør koden så kort som mulig.
Der må kun bruges standard liberys/headers ect.

Her er hvad jeg er nået frem til:
Fold kodeboks ind/udKode 


Det vigtigste man bør lægge mærke til her er at vectoren er af typen unsigned long (32 bit), men variablen test er af typen unsigned long long (64 bit), dette har naturligvis en årsag.
Når man tester om en tal er et primtal, tester man som bekendt (medmindre man bruger mystiske algoritmer og den slags) om de primtal der er mindre en tallet går op i, dog er det ikke nødvengidt at teste primtal størrer end kvardratroden at primtalet op i test tallet (det her kunne formuleres bedre)
en unsigned long long kan max indeholde værdien 2^64-1 og en unsigned long værdien 2^32-1.
Kvardratroden af førstnævnte er lig med
4294967295,9999999998835846781731
det er lige 0,9999999998835846781731 mere end en unsigned long kan indeholde, detter er naturligvis ikke et problem, da vi ikke regner med kommatal her, vi tester kun med primtal der er mindre eller er lig med kvardratroden af tallet der skal testes, så vi kan med fordel runde ned, hvilket vil sige at vi ikke har brug for at gemme primtal størrer en typen unsigned long.
Det er hvad jeg kalder effektivitet ;-)

Nuvel, jeg lod mig vist rive lidt med, hvad jeg egenlig ville hvar at udfordre alle genierne herinde til at gøre det bedre og hvis ingen skulle have lyst til at gøre et forsøg, er jeg stadig lidt utilfreds med strukturen, men hvis jeg gør som jeg gerne vil, brokker kompileren sig over at en eller anden iso standard ikke bliver overholdt.

[Redigeret d. 08/02-06 22:57:39 af Felix Nielsen]

[Redigeret d. 08/02-06 22:58:42 af Felix Nielsen]

[Redigeret d. 09/02-06 00:53:14 af Felix Nielsen]



Kommer lige i tanke om at den person jeg har konveseret med på nyhedsgrupperne har givet mig noget kode som jeg ikke fatter en bregne af, men det skal da ikke forhindre andre i at blive inspireret og evt. forklare det for mig ;-)

her er koden med kommentarer:
Fold kodeboks ind/udKode 




Har fiflet lidt med din kode og dermed fjernet is_prime:
Fold kodeboks ind/udKode 




Har fiflet lidt med din kode og dermed fjernet is_prime:
Fold kodeboks ind/udKode 


Med fare for at lyde utaknemmelig og respektløs...
Det virker ikke og giver iøvrigt ingen menning...



Suk! Utak er verdens løn :D
Nå, spøg til side:

Jeg har taget denne del af din kode
Fold kodeboks ind/udKode 

Og lavet den om til denne kode (der havde indsneget sig nogle fejl i de fremhævede dele)
Fold kodeboks ind/udKode 

Da du alligevel har en unsigned long long i kan du lige så godt flytte unsigned long long test samme sted hen. Det sparer lidt kode.

root=sqrt(test) kan lige så godt være i yderste FOR-loop, sparer en linie, men ellers intet.

Yderste FOR-loop: test!=1 kan lige så godt erstattes med true

Når test%p[index]==0) er sand, er meningen med prime=false, at næste tal skal testes. For ikke unødigt at gå ned til IF-sætningerne efter inderste løkke, udføres bare samme kode som is_prime==false ville have medført.

Efter min ændring vides nu med sikkerhed at if(is_prime==true) er sand efter inderste løkke, og derfor kan if(is_prime) helt fjernes.

Desværre ændrer det ikke væsentligt ved hastigheden, og det er på grund af to ting: 1) Måden du gemmer tal i filen. 2) Brugen af deque.
1) Primtallene gemmes i filen som tal der kan læses af mennesker. Så der skal en konvertering til, fra unsigned long long til char[], hver gang der gemmes, og det er noget der tager tid!
Jeg tvivler på, at du nogensinde får brug for, at læses indholdet af filen med dine egne øjne. Så det må være rigeligt at gemme primtallene som unsigned long long datatype. Det sparer iøvrigt plads når primtallene bliver meget store.
2) Når deque mangler plads, allokerer den mere plads. Om den så også kopierer alle de gamle data til den nye plads, er jeg ikke klar over, men hvis den gør..., puha en tidsrøver.
Det interessante er, at du ikke har behov for at have hurtig adgang til alle primtallene, da du kun bruger dem der er mindre end kvadratroden af test.

Jeg måtte lige prøve om det kunne lade sig gøre, at ændre ved disse to punkter og fandt frem til denne kode:
Fold kodeboks ind/udKode 

Min compiler gider ikke æde unsigned long long, så jeg bruger andre typer, men resultatet bør være det samme.
rootarray er jo ikke så stor, men med primtal nummer 65536 = 821.641 kan man teste tal helt op til 675.093.932.881



<< < 123 > >>
t