Memory Error wegen zu grosser List

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
raorao
User
Beiträge: 24
Registriert: Mittwoch 30. Dezember 2009, 15:35

Hoi mitenand!

Um Primzahlen zu generieren nutze ich ein Programm, das auf dem Sieb des Eratosthenes aufbaut:

Code: Alles auswählen

class Prim(object):
    # Folgender Funktionsaufruf liefert alle Primzahlen unter 1000:
    # primes = MyMath.Prim(1000).getPrimes()
    def __init__(self, limit):
        self.limit = limit
        self.gestrichen = [False] * (self.limit / 2)
        self.calculate()

    def calculate(self):
        i = 3
        while i*i <= self.limit:
            if self.gestrichen[i - 2] == False:
                # i ist prim, streiche seine Vielfache
                a = i*i / 2
                for j in xrange(a, (self.limit / 2),i):
                    self.gestrichen[j] = True
            i += 2

    def getPrimes(self):
        p = [2]
        for i in xrange(1, (self.limit / 2)):
            if self.gestrichen[i] == False:
                p.append(2 * i + 1)
        return p
Bei Zahlen bis 250000000 funktioniert dies auch tiptop, danach wird allerdings ein MemoryError erzeugt, da die anzulegende Liste in Zeile 7 maximal 250 000 000 boolsche Werte schlucken kann... Hat jemand eine Idee, wie man trotzdem effizient grössere Primzahlen generieren könnte? Ich vermute fast, dass die Lösung über einen Generator führt, da dann im Speicher nicht jedes Mal die ganze Liste aufgebaut werden muss. Leider habe ich aber keine Ahnung wie der Generator für diesen Zweck aussehen könnte... Herzlichen Dank für eure Hilfe!
raorao
Zuletzt geändert von Anonymous am Freitag 25. Juni 2010, 13:17, insgesamt 2-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

Warum du 250.000.000 (250 Mio) Zahlen speichern willst, frag ich einfach mal nicht.

Aber eine primitive Lösung wäre, dass du die Ergebnisse in mehrere Liste segmentierst / aufteilst.

d.h. du hast eine Hauptstruktur in welcher du die Teillisten speicherst. Jede dieser Teillisten kann dann bis zu 250 Mio zahlen speichern.
Suchen der Zahlen wäre dann auch (wenn man keinen vernünftigen Such-Alg implementiert) wenigstens nicht linear.

Interessant fände ich trotzdem zu wissen, was du mit den ganzen primzahlen willst ? :roll:
raorao
User
Beiträge: 24
Registriert: Mittwoch 30. Dezember 2009, 15:35

Besten Dank für die schnelle Antwort. Versuche gerade die Aufgabe 58 aus Eulers Projekt zu lösen und dafür brauch ich offensichtlich Primzahlen,die grösser 250 000 000 sind, denn bis dahin sinkt die Quote nicht unter 10% (bis dahin bei ca. 13 %). Dabei stösst mein Primzahlengenerator aber an seine Grenzen, obwohl ich den Code mittlerweile soweit optimiert habe, dass die Berechnung nicht einmal mehr halb so lange dauert und auch Zahlen bis 500 000 000 möglich sind, da nur mehr ungerade Zahlen betrachtet werden (siehe mittlerweile editierter Code oben).
Habe natürlich über eine Aufteilung in Teillisten nachgedacht, finde dies jedoch keine schöne Lösung. Sollte mir nichts eleganteres einfallen werd ichs aber natürlich so probieren...
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

raorao hat geschrieben:Besten Dank für die schnelle Antwort. Versuche gerade die Aufgabe 58 aus Eulers Projekt zu lösen und dafür brauch ich offensichtlich Primzahlen,die grösser 250 000 000 sind ...
Zunächst mal zum 1. Post: Mit einem Generator kannst du ein Sieb nicht realisieren, weil du ja immer wieder das ganze Feld durchläufst und auf jede Zelle des Feldes zugreifen können musst.
Eine kleine Verbesserung mit großer Wirkung - nämlich Reduktion des Siebes auf ungerade Zahlen - hast du ja inzwischen selbst entdeckt. [Im übrigen sollte man einmal geposteten Code nicht nachträglich verändern - dadurch werden ggf. nachfolgende Posts, die sich darauf beziehen, unverständlich] Das könntest du noch weiter treiben, indem du z.B. von vornherein auch die Vielfachen von 3 aus dem Sieb nimmst. Dann bist du schon bei 1/3 der Ursprungsgröße. Damit ist das Sieben dann aber nicht mehr ganz so trivial wie bisher. Wenn dir das nicht reicht, kannst du das Boolesche Feld bitbasiert einsetzen und dadurch nochmal auf 1/8 der vorherigen Größe reduzieren. Hinsichtlich der Performance dürfte das aber - solange du Python verwendest - eher ein Rückschritt sein.

All das ist aber für die Lösung von Euler 58 irrelevant, weil der von dir gewählte Ansatz ineffizient ist. Statt ALLE Primzahlen zu erzeugen, von denen du dann doch nur einen kleinen Teil brauchst, ist es viel effizienter, nur die Zahlen überhaupt zu erzeugen, die als Zahlen der Diagonalen auftauchen und für diese Zahlen zu prüfen, ob sie prim sind. Dafür kannst du z.B. den Miller-Rabin-Primzahltest verwenden.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Alternativ wartest du ein paar Jahre, bis dein Hauptspeicher ausreicht. ;)

:twisted:
raorao
User
Beiträge: 24
Registriert: Mittwoch 30. Dezember 2009, 15:35

Super, herzlichen Dank. Liste ist somit überflüssig, jahrelanges warten hat mich angesch..., deshalb brav den Miller-Rabin Test implementiert, vielen Dank für den Tipp, liefert in 4 Sekunden das richtige Resultat, das wäre mit der andern Methode undenkbar wenn man sieht, wie gross die Primzahlen werden...
Bis bald, würd mich ja schliesslich erstaunen wenn Problem 59 reibungsfrei funktionieren würde... :)
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

mkesper hat geschrieben:Alternativ wartest du ein paar Jahre, bis dein Hauptspeicher ausreicht. ;)

:twisted:
Hey cool, ich wuste garnicht das der RAM mit der Zeit wächst! :lol:
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Py-Prog hat geschrieben:Hey cool, ich wuste garnicht das der RAM mit der Zeit wächst! :lol:
Naja, eben regelmäßig gießen und der Sonne aussetzen. Genau das, was kleine Transistoren am liebsten haben, wenn sie sich fleißig vermehren sollen. :)
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Naja, eben regelmäßig gießen und der Sonne aussetzen. Genau das, was kleine Transistoren am liebsten haben, wenn sie sich fleißig vermehren sollen. :)
Ich hab noch zwei 512MB Chips rumligen, die muss ich gleich einplanzen. :D
Eine Frage noch wielange muss ich mein 2 Kerner gießen das ich ein Intel Core i7-980X (6 Kerner) bekomme?
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Die RAM-Chips sind über den Winter eingegangen. :cry: :cry: :cry:Wieso, wiesooooooooo?
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Antworten