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]



Ny kode igen igen, hører gerne om en måde hvorpå det kan køre kortere, pænere og simplere.
Fold kodeboks ind/udKode 




Legede lidt med koden i main. Fik lavet lidt optimering:

Fold kodeboks ind/udKode 

Af mine compilere lavede Digital Mars den hurtigste kode, den klarer det på 10 sekunder.
Med MinGW tager det med optimering slået til (-O2) 15 sek.

__int64 er en windows 64 bit type.

[Redigeret d. 13/02-06 00:19:17 af Bertel Brander]



Legede lidt med koden i main. Fik lavet lidt optimering:

Fold kodeboks ind/udKode 

Af mine compilere lavede Digital Mars den hurtigste kode, den klarer det på 10 sekunder.
Med MinGW tager det med optimering slået til (-O2) 15 sek.

__int64 er en windows 64 bit type.

[Redigeret d. 13/02-06 00:19:17 af Bertel Brander]

Ser meget interesant ud, vil tage et kig på det.




Jeg har kigget på koden og må sige at jeg har problemmer med at se hvori optimeringen består.
Jeg er udemærket bekendt med __int64, men da visse kompilere skulle have problemmer med den, er jeg gået over til unsigned long long istedet, det skulle være det samme og jeg mærker da heller ikke nogen forskel.

Du har incoorpereret noget tids halløj og det skal du have tak for da jeg skal bruge netop denne funktion i et andet project, men ikke har kunne få det til at virke.


Til orientering kan jeg fortælle evt. intereseret at jeg har fundet de eksakte begrænsninger for hvor meget en vector kan indeholde:

std::vector<char> b1(268435456)
std::vector<short> b2(134217728)
std::vector<long> b4(67108864)
std::vector<long long> b8(33554432)

det er jo nemt nok at se systemet, men vi kan køre det kort med at sige at en vector max kan indeholde 256 MB data.
Så ved i det.

I den forbindelse kunne jeg godt tænke mig at få svar på et spørgsmål.

Jeg vil jo gerne, når en vector er fuld, kunne oprette en ny automatisk, noget ala:
int N = 0;
std::vector<type> vector_nummer_{N}(0);

Kan dette overhovedet lade sig gøre, hvad er der evt. af alternativer, ect.



Man kan spørge en container hvor mange elementer den kan indeholde:

Fold kodeboks ind/udKode 


De fire compilere jeg pt har på min PC svarer alle:
1073741823
536870911

Disse tal er compiler og platform afhængige.



Jeg har kigget på koden og må sige at jeg har problemmer med at se hvori optimeringen består.


Jeg kalder kun sqrt og read én gang for hver runde i den inderste loop; det gør en forskel.



Ja det er jo rigtigt, godt tænkt.

Nuvel, jeg er jo nået et stykke videre i henhold til hvordan et sådan program kan/bør opbygges og er nået til den konklusion at jeg bliver nødt til at have lavet en class eller lign. der kan opfatte to eller flere vectorer af samme type som én og samtidig oprette nye hvis dette skulle blive nøvendigt.

Hvis nogen har lyst til at rode lidt med det koncept ville det være interessant, jeg vil dog ikke påtage mig det da jeg da roder mig ud i noget jeg endnu ikke har det fjerneste forstand på.



Man kan spørge en container hvor mange elementer den kan indeholde:

Fold kodeboks ind/udKode 


De fire compilere jeg pt har på min PC svarer alle:
1073741823
536870911

Disse tal er compiler og platform afhængige.

Det er sjovt, det visser samme resultat på min, men vectorne kan reelt indeholde max_size()+1, det er test for både char, short, long og long long, hvor denne forskel på én har jeg dog ingen idé om.




Ny kode igen igen.
Bruger nu deque istedet for vector, er blevet fortalt at det skulle løse problemet med begrænsingerne for størrelsen.
Og så har jeg tiolføjet lidt tekst og så´n.

Fold kodeboks ind/udKode 




Ja det går stærk, nu er minsanten kommet endnu en opdatering, men jeg har også en hel del spørsmål jeg ønsker besvaret, men først koden.

Fold kodeboks ind/udKode 


1)
Jeg har læst at functionen 'copy()' er defineret i headeren 'algoritm', er det rigtigt? Det fungerer jo fint for mig uden, men hvis vi antager at jeg ikke tager fejl, ville det så ikke være mest hensigtsmægsigt at includere denne header selvom jeg reelt ikke bruger den?

2)
Som det kan læses af koden læser og skriver jeg nu til disken binært, dette skulle spare en hel del plads, men jeg er kommet i tvivl på et par punkter.

2.1)
De tal den læser fra start bliver inlæst fint og uden problemer, men jeg har endnu ikke brugt grænsen der hedder 0xffffffff, så det er der jo ikke noget at sige til, men når jeg når så langt, er det så ikke muligt at det kan skabe problemer? Jeg mener disse iteratorer der bliver brugt er jo af typen unsigned long, hvad vil der ske hvis den prøver at indlæse en værdi som typen ikke kan indeholde?

2.2)
Under alle omstændigheder har jeg brug for at sætte en stop klods så den ikke kan indlæse værdier der er størrer end den type som dequen er defineret som, men hvordan?
Vil dette løse ovenstående problem?

2.3)
Disse parametre som bliver brugt i forhold til istream og ostream; er det evt. nogen af den jeg kan undvære, eller er der mon nogen jeg mangler? Det virker, men derfor kan jeg jo godt have gjort en fejl.

2.4)
Jeg har fået denne besked fra en nyhedsgruppe:
---
Note, if you go with a binary file the same file won't necessarily work
on all platforms (hint: lookup "endian".) There are things you can do to
fix that...
---
Jeg har gjort som foreslået, men er ikke blevet klogere, er det nogen jeg reelt bør bekymre mig om når filen kun skal bruges på den platform den er kompileret til?
Hvis ja, ()også gerne hvis nej) er der en der evt. ved hvad det handler om og kan forklare lidt?

3)
Fra samme nyhedsgruppe:
---

You don't need a deque, or any other kind of container for prime
numbers. Primes are already a sequence, and you can represent them with an iterator.
---
Jeg er nogenlunde sikker på at jeg forstår meningen med ovenstående, men...
Er det korrekt?
Er det for avanceret for mig?

På forhånd tak, håber at få nogle gode/interessante svar.



<< < 123 > >>
t