cybton.com
Über uns | Jobs | Werbung | Sitemap | AGB | Impressum | Hilfe ?
 Kostenlos anmelden)
Forum
Aktuellste Beiträge
Forenregeln

Community
BB-Codes
Tags
Chat
Suche (Web)
Wer ist online?
Top-User

Basar


Statistik
Mitglieder gesamt: 68573
Mitglieder online: 7
Gäste online: 3
mehr...

Anzeige
Forum » Forum: Softwareprogrammierung » Thread: Primzahlengenerator

Thread: Primzahlengenerator

Seite 3 von 41234

17.09.2008 19:06 Uhr

 

Status: online
So nun habe ich das mit einem Bool Array und nem Haufen Zeigerarithmetik gelöst und es wird bis zur maximalen Zahl die noch eine andere Zahl rausschmeissen kann berechnet und nicht mehr alles.

Das Programm braucht bei mir nun für eine Milliarde (1.000.000.000) nur noch 38.016 Sekunden und dabei sogar unter 1GB RAM.

Neuste Version ist als V3 oben. (Die anderen beiden sind jetzt V1 und V2)
1 mal bearbeitet
18.09.2008 12:04 Uhr

 

Status: offline
Saubere Sache  :glad: 

Rennt verdammt gut für den Algorithmus.
___________________________
Having no way as way.
18.09.2008 12:46 Uhr

 

bmk
Moderator
Status: offline
Ich überlege die ganze Zeit, ob es tatsächlich nötig ist, das gesamte Array von Anfang an im Speicher zu haben.

Könnte es nicht auch möglich sein, dass man einfach einen Teilbereich berechnet (also zB die Zahlen von 1 bis 100 nach Primzahlen durchsucht), und aus dem verbleibenden "Gitter" dann ein neues Gitter für einen größeren Bereich erstellt?

Ein Beispiel: Wenn ich die "2" als Primzahl gerade ausgeschlossen habe, fehlen im Gitter alle Vielfache von 2. Die müssten, wenn ich eine kleine Matrix abgearbeitet habe und diese Matrix dann für einen größeren Bereich vervielfältige, gar nicht mehr mitkopiert werden.

Es könnte (und ich wähle absichtlich "könnte") also vielleicht (...) möglich sein, die Anfangsphase, in der sehr viele Zahlen weggesiebt werden, wesentlich zu verkürzen. Da kommen zwar ein paar Kopieroperationen dazu, aber die sollten im Gegensatz zu den ersparten Siebe-Operationen eher vernachlässigbar sein. Glaub ich...

Kann sich irgendwer dazu aufraffen, sich das mal durch den Kopf gehen zu lassen...?


Ganz anderer Punkt: Speicherstruktur.
Du verwendest momentan ein Array. Jetzt mal Abgesehen davon, dass man die Zahlen als integer, bool oder bit speichern kann: Ab dem ersten Siebe-Schritt ist das Array zur Hälfte leer, ab dem zweiten nur noch zu einem Drittel. Da würde sich als Speicherstruktur doch ein Sparse Array anbieten, oder?
3 mal bearbeitet
___________________________
Let's code responsibly...
Webcrawler -- Portal für Dirigenten -- Musikverein Königstetten
18.09.2008 14:08 Uhr

 

Status: offline
Hmm, das mit dem Sieb einfach versetzen hört sich gut an. Doch (bitte nicht hauen wenn ich mich irre) hat folgendes Problem: Wenn ich nun die Zahlen von 1 bis 100 siebe, ist der erste Platz keine Primzahl. Doch wenn ich das gleiche Sieb nun auf die Zahlen von 101 bis 200 anwende, wäre auch 101 keine Primzahl. (Das ist doch eine oder  :lol:  )

Man müsste das Sieb dann für jeden Zahlenbereich in die richtige Richtung "versetzen" damit es passt, oder irre ich mich? Das würde aber erst wieder einiges an Kalkulationsaufwand bedeuten und insbesondere für die Indexer Mulitplikationen bedeuten die ja bekanntlich sehr teuer sind.

Edit:/ Zudem, das erste Mal ist ja 2 oder 3 oder 7 usw. eine Primzahl. Das heißt, man müsste sich zusätzlich für jeden Bereich ein Ausnahmenraster merken.
3 mal bearbeitet
___________________________
Having no way as way.
18.09.2008 20:45 Uhr

 

Status: offline
Zitat:
Fehler beim Anfordern des benötigten Speichers, Programm wird beendet.

AMD Opteron 185 2x2.6 gHz
3 GB RAM
Win XP Pro 32Bit
Zahlen: 0 - 1 000 000 000

edit:// wär schön, wenn du irgendwo die versionsnummer vermerke würdest!
1 mal bearbeitet
___________________________
MFG Jan
"funzt nicht" ist keine gültige Fehlerbeschreibung!*haarerauf*
http://www.sysprofile.de/id30821
18.09.2008 21:45 Uhr

 

bmk
Moderator
Status: offline
Zitat:
Wenn ich nun die Zahlen von 1 bis 100 siebe, ist der erste Platz keine Primzahl.

Was ich bei meinen ganzen Überlegungen seither beim Heimfahren im Zug gemerkt habe: Dass die Eins keine Primzahl ist, muss man bei derartigen Überlegungen weglassen. Sie erfüllt die Grundbedingungen einer PZ (nur durch Eins und sich selbst teilbar...) und ist sozusagen nur "per Definition" keine Primzahl -- bei der Berechnung des Siebes schon. Erst ganz zum Schluss nimmt man sie dann aus der Lösungsmenge aus.

Ich hab schon eine ziemlich gute Idee, muss die aber erst so in Worte fassen, dass der Algorithmus verständlich ist. So wie's aussieht, dürfte das aber sowohl sauschnell gehen als auch kaum Speicher brauchen. Ich meld mich am Samstag wieder, morgen hab ich keine Zeit dafür. Aber mich kribbelt's schon in den Fingern ;-)

Stay tuned.
___________________________
Let's code responsibly...
Webcrawler -- Portal für Dirigenten -- Musikverein Königstetten
19.09.2008 12:21 Uhr

 

bmk
Moderator
Status: offline
Sorry, for Doppelposts.

@BPhoenix: Könntest du in deinen Code mal einen kleinen Zähler einbauen, der zählt, wie oft hier verglichen wird? Also jedesmal, wenn du schaust, ob eine Zahl durch eine andere teilbar ist, zählst du eines hoch.

Mich würde sehr interessieren, wie hier die Statistik für 10, 100, 1000, ... Ausgangszahlen aussieht.
Das wäre auch ein sehr gutes Kriterium, um deine Algorithmen gegeneinander zu vergleichen - unabhängig von der verfügbaren Techenleistung.

LG, bmk.
___________________________
Let's code responsibly...
Webcrawler -- Portal für Dirigenten -- Musikverein Königstetten
20.09.2008 15:10 Uhr

 

Status: online
Zitat:
Fehler beim Anfordern des benötigten Speichers, Programm wird beendet.

Das ganze kam innerhalb des Programmes, richtig? Ich habe da eine kleine Überprüfung reingebaut, nämlich nach dem der Speicher angefordert wird, wird geschaut ob dieser Vorgang gelungen ist oder nicht.
Der Hauptgrund wieso dies misslingen sollte, ist wenn das Programm versucht einen größeren Speicher anzufordern als zusammenhängend verfügbar.

Hast du ggf. die Auslagerungsdatei deaktiviert? Hattest du einen Haufen Anwendungen oder ein paar wenige Speicherlastige Anwendungen laufen? Ansonsten wenn das nicht zutrifft, hat es Windows einfach nicht geschafft den Speicher so umzustrukturieren, dass ein so großer Speicherbereich verfügbar war. Denn der Speicher fragmentiert nach der Zeit aus, es kann zwar sein, dass du genug Speicher frei hattest aber eben nicht genug an einem Stück.

Probier einfach mal es nochmal auszuführen, ggf. mit weniger Programmen im Hintergrund und ggf. mit aktivierter Auslagerungsdatei, dann wird entweder der Rest ausgelagert oder mein Arrays in dieser erstellt.

Zitat:
Mich würde sehr interessieren, wie hier die Statistik für 10, 100, 1000, ... Ausgangszahlen aussieht.
Das wäre auch ein sehr gutes Kriterium, um deine Algorithmen gegeneinander zu vergleichen - unabhängig von der verfügbaren Techenleistung.

Das ist so leider nicht ganz möglich, denn V2 und V3 prüfen beide gleich oft (sofern ich bei V2 das mit der Wurzel integriert habe aber das hatte ich bei V2 wenn es nicht drin ist einfach nur vergessen, der Rest ist zumindest identisch ausser, wie die Sachen gespeichert werden.) Was noch hinzukommt ist, dass ich bei V2 und V3 gar nicht teste ob eine Primzahl durch irgendwas teilbar ist. Sondern einfach alle vielfachen von einer Zahl rausnehme und da ist das Verfahren bei V2 und V3 identisch, dieses Verfahren ist auf jedenfall schneller als das in V1 welches noch alles durchprobierte.

Oder du meintest wie viele Rechenzyklen meine Algorithmen brauchen, das Problem hierbei ist jedoch, dass dies nicht so einfach ermittelt werden kann. Denn 1. müsste ich wissen was GENAU mein Compiler aus dem C Code macht was innerhalb von C eigentlich unmöglich ist. In Assembler wäre dies kein Problem, da jeder Befehl in einen Maschinencode umgewandelt wird und da die Anzahl der Taktzyklen rausgefunden werden kann. Das 2. Problem ist, dass jeder eine andere Architektur besitzt und so eine gewisse Anweisung von einem Prozessor vielleicht 2 Takte braucht und beim anderen 4 Takte damit diese Anweisung ausgeführt werden kann (Stichwort CPU-Optimierung). Ausserdem wird mein Programm nicht direkt von der Hardware ausgeführt, denn es sind noch ein paar Schichten vom Betriebssystem dazwischen und das bedeutet, dass ein Algorithmus der theoretisch flotter ist, praktisch langsamer sein kann.

Es ist also vollkommen sinnlos zu messen wie oft ein Programm was macht das einzige was bei einem solchen Algorithmus zählt ist wie schnell dieser im Endeffekt ist und das mache ich ja eigentlich schon mit meiner Zeitmessung.

Ausserdem wüsste ich gar nicht wann ich eine Variable hochzählen sollte, damit man diese statistisch sinnvoll verwerten könnte, besonders nicht bei 2 vollkommen unterschiedlichen Algorithmen wie V1 und V2.
Zitat:
Hmm, das mit dem Sieb einfach versetzen hört sich gut an. Doch (bitte nicht hauen wenn ich mich irre) hat folgendes Problem: Wenn ich nun die Zahlen von 1 bis 100 siebe, ist der erste Platz keine Primzahl. Doch wenn ich das gleiche Sieb nun auf die Zahlen von 101 bis 200 anwende, wäre auch 101 keine Primzahl. (Das ist doch eine oder  :lol:  )

Naja das mit der 1 wäre absolut kein Problem, ich nehme einfach ein Array mit 1-100 und frage diesen einen besonderen Fall ab und wenn das zutrifft vermerke ich 1 als nicht Primzahl und 2 als Primzahl.
Das Problem hierbei ist, dass das mit dem verschieben des Gitters einfach nicht funktioniert!
Nehmen wir ein Gitter von 1-10:
1 = nicht prim
2 = prim
3 = prim
4 = nicht prim
5 = prim
6 = nicht prim
7 = prim
8 = nicht prim
9 = nicht prim
10 = nicht prim
und versetzen das nun auf 11-20, dann hätte ich folgendes:
11 = nicht prim
12 = prim
13 = prim
14 = nicht prim
15 = prim
16 = nicht prim
17 = prim
18 = nicht prim
19 = nicht prim
20 = nicht prim
Hier sehe ich, dass ich bei 11 nicht Prim stehen habe und bei 15 Prim was beides falsch ist und somit hätte ich das Problem, dass ich bei keiner der Zahlen nun wirklich weis ob Prim oder nicht Prim, da beides möglich ist und so müsste ich beide darauf testen ob oder ob sie nicht Prim sind und dadurch hätte ich absolut keine Vorteile. Und sowas entsteht auch bei einem Gitter von 100, von 1000 oder bei jeder x-beliebigen Gittergröße.



Aber mir ist ein anderer alternativer Algorithmus eingefallen. Denn es gilt ja, dass jede natürliche Zahl größer als 1, als Produkt einer Primzahl dargestellt werden kann. Bei Primzahlen ist aber das einzige mögliche Produk 1*sich selbst(was eine Primzahl ist).

Der Algorithmus würde also bei 2 anfangen und schauen ob es eine Primzahl gibt mit der Multipliziert werden kann (nämlich durch eine Division). Da es keine gibt (weil bisher keine gefunden wurden), ist 2 eine Primzahl. Dann wird bei 3 getestet und geschaut ob eine andere Primzahl reinpasst 3/2 != x€N also nein. Dann wird bei 4 getestet und hier sieht man sofort 4/2=2 also keine Primzahl und ab zur nächsten Zahl.
Wenn ich nun rausfinden könnte wie viele Primzahlen es maximal gibt bei einer gewissen Grenze könnte ich auch nur maximal so viel Speicher anfordern.

Dies wäre zwar rechenintensiver als V2 und V3, aber weniger speicherlastig, da nur die Primzahlen gespeichert werden und maximal so viel Speicher belegt wird wie maximal Primzahlen vorhanden sind, sofern ich rausfinden kann wie ich das berechne, diesen Speicher könnte ich theoretisch anfangs erst klein halten und später ständig erweitern und beim Auslagern wäre der Algorithmus sogar schneller, da jeder Wert nur einmal in die Berechnung reingenommen wird und nicht ständig ein ganzer Haufen an Werten aktualisiert wird.

Es ist eine Art Kombination aus beiden Verfahren.
1 mal bearbeitet
20.09.2008 15:23 Uhr

 

Status: offline
Zitat:
Hast du ggf. die Auslagerungsdatei deaktiviert?

Ja hab ich! Aber alles andere läuft einwandfrei

Zitat:
Hattest du einen Haufen Anwendungen oder ein paar wenige Speicherlastige Anwendungen laufen? Ansonsten wenn das nicht zutrifft, hat es Windows einfach nicht geschafft den Speicher so umzustrukturieren, dass ein so großer Speicherbereich verfügbar war. Denn der Speicher fragmentiert nach der Zeit aus, es kann zwar sein, dass du genug Speicher frei hattest aber eben nicht genug an einem Stück.

Prozessliste ist im Anhang
Ich muss dazusagen, dass Windows schon sein ein paar Sunden läuft und ich gespielt habe.

Warum sollte dein Programm mit knapp 2 GB nicht zurecht kommen?
1 Datei angehängt
___________________________
MFG Jan
"funzt nicht" ist keine gültige Fehlerbeschreibung!*haarerauf*
http://www.sysprofile.de/id30821
20.09.2008 15:41 Uhr

 

bmk
Moderator
Status: offline
Das mit dem Versetzen des Gitters habe ich mal eine Nacht lang durchdacht.
Im Prinzip ist die Frage (an der du das Problem richtigerweise aufgezeigt hast, und auch an ein paar neuen grauen Haaren schuld ist) folgende: Wenn ich gerade X Primzahlen gefunden und aussortiert habe, wie große ( bzw. klein) ist jener Bereich, der gefahrlos verschoben werden kann. Also die Frage nach der gesicherten Gittergröße abhängig vom momentanen Siebefortschritt.

Ich habe hier allerdings das Problem, dass ich mit Zettel und Bleistift bei meinen Überlegungen sehr rasch an die Grenzen stoße. Warum, wird man gleich sehen.
PHP:
1
2
3
4
5
6
Primzahl   Gitter fix bis
 1                1
 2                2
 3                6
 5               30
 7              210
Es sieht also aus, als ob die gesicherte Gittergröße gG eine direkte Funktion der bisherigen Primzahlen ist:
gG(x) = Produkt aller Primzahlen kleiner gleich x


Nun ist auch klar, warum ich mit Zettel und Bleistift an eine Grenze stoße: Die nächste PZ nach 7 wäre die 11, und hier ginge das Gitter schon bis gG(11) = 2310. Das wäre schon etwas mühsam. ;-)

Die Vorgehensweise sah bei mir so aus:
Man beginnt bei 1.
Nächste Zahl: 2
Man schreibt alle Zahlen bis zu gG(2) = 2 hin und noch eine zusätzlich, also: 1 2 3
Dann stricht man alle Zahlen heraus, die durch 2 teilbar sind. Übrig bleibt: 1 3
Durch dies beiden Zahlen ist der Abstand definiert, der derzeit gilt.

Nächste Zahl: 3
Die Reihe wird fortgesetzt bis zu gG(3) = 6, plus eine zusätzliche: 1 3 5 7
Nun wird mit 3 gesiebt. Übrig bleibt: 1 5 7
Das ist das neue Muster: der erste Abstand ist 4, der zweite ist 2.

Nächste Zahl: 5
Fortsetzen bis zu gG(5) = 30, plus eine zusätzliche; nun wird's interessant: wir wenden einfach das Muster an, das wir vorher erhalten haben: einmal 4 dazuzählen, einmal 2 dazuzählen, dann wieder von vorne: 1 5 7 11 13 17 19 23 25 29 31
Nun wird die 5 gesiebt, es fallen 5 und 25 heraus: 1 7 11 13 17 19 13 29 31
Das neue Muster lautet also: 6, 4, 2, 4, 2, 4, 6, 2

Nächste Zahl: 7
Fortsetzen bis zu gG(7) = 210, plus eine zusätzliche.
Sieben aller Zahlen, die durch 7 Teilbar sind. Es fallen weg: 7, 49, 77. 91, 133, 161, 203

Das klingt jetzt alles ziemlich heftig, ist aber im Prinzip schweineeinfach. Das Coole daran ist, dass in jedem Schritt immer nur jene Zahlen zum bisherigen Sieb dazukommen, die fix und fertig gesiebt sind. In jedem Schritt wird das Sieb aus dem vorigen Schritt nicht mehr angerührt.

Als Vergleich: Will man alle Primzahlen bis zur 100 (dem klassischen Siebe-Beispiel, wie es auch in Wikipedia dargestellt wird), so braucht der Vorgang insgesamt etwa 25 Speicherplätze, und es werden nur 9 (!) Zahlen herausgestrichen.
Das sollte eigentlich ziemlich gut skalieren. :-)


Ich bin in CPP leider nicht mehr so ganz fit. Glaubst du, du kannst den Algorithmus mal implementieren?
2 mal bearbeitet
___________________________
Let's code responsibly...
Webcrawler -- Portal für Dirigenten -- Musikverein Königstetten
Seite 3 von 41234
Ähnliche Threads Forum Ähnlichkeitsgrad
 Spieleprogrammierung - und kein Einstieg Softwareprogrammierung 1
 [C++]Allegro Installieren unter WinXP mit Visual C++ als Entwicklungsumgebung Softwareprogrammierung 1
 Asp.net Buch C# Website & Webprogrammierung 1
 c++ compiler Softwareprogrammierung 1
 Dateicontainer für HTML-Games-Server Softwareprogrammierung 1
 [Vermutlich gelöst] FTP mit C? Softwareprogrammierung 1
 MinGW "g++: installation problem, cannot exec `cc1plus': No such file or directory" Softwareprogrammierung 1
nach obennach oben

Copyright © 2010 cybton-network

Google
Partner: #Musik - Dein Internetradio - nexem. - .wir machen news - s.Oliver Onlineshop für Schuhe
ANEXIA - PHP Entwicklung - Dockers- Think Schuhe - der eigene Weg - Paul Green Damenschuhe - Bequeme Geox Schuhe - Web-Entwicklung - Schueler.CC @ nexem - SMSjobs