Primzahlen

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

LordArtus

Betreff: Primzahlen

BeitragSa, Aug 25, 2007 22:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo ,
hab ein Prog. in Bmax geschrieben , welches Primzahlen berechnet.

Code: [AUSKLAPPEN]

z=1
bis=100000000
counter=0

Type MyType
   Field prim
   
   Function Create:MyType(zzz)
      Local e:MyType=New MyType
      e.prim=zzz
      Return e
   End Function
End Type

Local PrimList:TList=New TList
PrimList.AddLast(MyType.Create(2))

memvar=GCMemAlloced()
time=MilliSecs()

For t=0 To bis
   
   zz=Sqr(z)
      
   For a:MyType=EachIn PrimList
      If (z Mod a.prim)=0
         PrimList.RemoveLast()
         Exit
      ElseIf a.prim>=zz
         counter=counter+1
         Print z 'An der Stelle ist z=PRIM
         Exit
      EndIf
   Next
   
   z=z+1
   PrimList.AddLast(MyType.Create(z))
   
Next

Print "Von 1 bis "+bis
Print "Menge der Primzahlen: "+counter
Print "Zeit : "+(MilliSecs()-time)/1000.0+" sek"
Print "Mem.Anfang: "+memvar+" bytes"
Print "Mem.Ende: "+GCMemAlloced()+" bytes"

While Not KeyHit(KEY_ESCAPE)
Wend

End



Problem an dem Code ist , dass die Liste immer grösser wird , bis 100.000.000 braucht das Prog. ca.280 MB an Arbeitsspeicher.
Da in der Liste alle Primzahlen enthalten sind , aber zur Berechnung der Primzahlen nur die Wurzel der grössten Primzahl in der Liste benötigt wird , ist der Rest in der Liste zur Laufzeit eigentlich überflüssig (reine RAM Verschwendung).
Nun , meine Frage:
hätte jemand nee Idee , wie ich die Liste kleiner halten könnte , ohne grösseren Performanceeinbrüchen , oder gibts schnellere Methoden um Primzahlen auszurechnen ?
Wäre sehr dankbar für Antworten.

MfG

LordArtus
 

#Reaper

Newsposter

BeitragSo, Aug 26, 2007 1:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Also jetzt ohen den Code genauer angeschaut zu haben, und ohen das ich mich mit Primzahlberechnungen auskenne:
Wenn du doch eh nur die größte, also auch die letzte berechnete Primzahl brauchst, warum nimmst du dann überhaupt eine Liste? Eine einzigste Variable dürfte da doch reichen, oder? Wink

Und schau mal in der Suche, gibt schon viele Threads zu dem Thema, dürften für dich dann auch interessant sein Wink
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

Smily

BeitragSo, Aug 26, 2007 1:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Wenn du doch eh nur die größte, also auch die letzte berechnete Primzahl brauchst, warum nimmst du dann überhaupt eine Liste? Eine einzigste Variable dürfte da doch reichen, oder?


Das wort einzige ist nicht steigerbar!
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org
 

Dreamora

BeitragSo, Aug 26, 2007 1:21
Antworten mit Zitat
Benutzer-Profile anzeigen
der elementarste fehler in dem algo ist das du 1 steps machst. Ab 3 kannst du jedoch garantieren dass der step mindestens 3 ist! (weil gerade kanns nie mehr werden). Damit halbiert sich der speicherbedarf schonma Wink

Deswegen würde ich von der For schleife abraten und ne while oder repeat nehmen.
In diese schleife gehst du dann rein, wenn die gesuchte zahl > 2 ist und benutzt fortan einfach nur noch + 2

dort kannst du dann auch weitere step optimierungen vornehmen solltest du das wünschen oder welche kennen.


Solltest du je speedprobleme haben: Nimm die Print raus und ersetz sie durch Filebefehle ... das geschreibsel ist eine der grössten speedbremsen weil die konsole nie dafür gedacht war sie so zuzuschreiben.



PS: ganz oben noch strict oder super strict rein, sonst sind local wertlos und der ganze code leidet drunter
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

#Reaper

Newsposter

BeitragSo, Aug 26, 2007 1:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Smily0412 hat Folgendes geschrieben:
Zitat:
Wenn du doch eh nur die größte, also auch die letzte berechnete Primzahl brauchst, warum nimmst du dann überhaupt eine Liste? Eine einzigste Variable dürfte da doch reichen, oder?


Das wort einzige ist nicht steigerbar!


Ot? :O
(Nja, sorry jetzt für weiteres OT):
Einzige, mehr Einzigste, am Einzigsten Razz Laughing
War keine Steigerung, kommt wohl eher von der Aussprache her Razz Wink Rolling Eyes
(Tjaja, Akzente Wink )


@Dreamora: Wenn ab 3 der Step 3 ist, käme man doch direkt zur Zahl 6, welche ja doch gerade ist..? Oder verstehe ich deine Aussage falsch..?
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

mahe

BeitragSo, Aug 26, 2007 1:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Step ist natürlich 2, was er in späterer Folge auch richtig geschrieben hat.
ʇɹǝıdɯnɹɹoʞ ɹnʇɐuƃıs - ǝpoɥʇǝɯ-ɹoɹɹıɯ ɹǝp uı ,ɹoɹɹǝ,
 

Dreamora

BeitragSo, Aug 26, 2007 1:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
z=z+1


Vielleicht missinterpretier ich das 1 auch einfach falsch Smile

Er prüft ob z prim ist, nicht ob t prim ist.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

LordArtus

BeitragSo, Aug 26, 2007 11:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Guten Morgen,
erstmal Danke für die Antworten.

Als erstes sage ich einfach : um die grösste Primzahl zu berechnen , brauche ich eh eine Liste mit Primzahlen von 2 bis zu der Wurzel der Zahl die ich berechnen will , und genau mit dem Prog. wird so eine Liste gemacht , bloss nicht bis zu der Wurzel (was ich mir eigentlich wünsche und das ist gerade das Prob.) , sondern bis zu der Zahl die ich berechnen will.(Und weil alle Primzahlen bis zu der berechneter Zahl in der Liste vorhanden sind ist auch der Arbeitsspeicher schon bei 280MB bei der "kleinen" Zahl von 100.000.000.Theoretisch könnte ich schon mit derzeitiger Liste bis 100.000.000^2 berechnen)

@Dreamora

Stimmt , der Printbefehl ist langsam , mit dauerts bei mir bis 100.000.000 ca. 739 sek. ohne Print (d.h. ohne jeglicher Ausgabe) ca. 449 sek. (AMD 64 4000).
Stimmt , mit z=z+2 und kleinen Eingriff müsste es viel schneller laufen Wink Danke. (Habs noch nicht überprüft, werde es aber heute Nachmittag testen)

MfG

LordArtus

p.s. Sorry für grammatische und orthographische Fehler und dass ich eventuell etwas vergessen habe zu schreiben , aber bin grad aufgestanden und noch kein Kaffee intus Wink
p.p.s eventuell wüsste vielleicht jemand wie ich die Variable "MyType.prim" kleinstmöglich in der Liste abspeichern kann ? (Es muss nicht ein Type sein)

LordArtus

BeitragSo, Aug 26, 2007 19:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi , nochmal ich.

Code: [AUSKLAPPEN]

z=1
bis=100 ' bis=Bis zur welcher Zahl sollen Primzahlen berechnet werden
bis=bis/2 ' Wegen z=z+2

Type MyType
   Field prim
   
   Function Create:MyType(zzz)
      Local e:MyType=New MyType
      e.prim=zzz
      Return e
   End Function
End Type

Local PrimList:TList=New TList
PrimList.AddLast(MyType.Create(3)) ' Ist der Anfangswert der Liste

memvar=GCMemAlloced()
time=MilliSecs()

For t=0 To bis
   
   zz=Sqr(z)
      
   For a:MyType=EachIn PrimList
      If (z Mod a.prim)=0
         PrimList.RemoveLast()
         Exit
      ElseIf a.prim>=zz
         Print z 'An der Stelle ist z=PRIM
         Exit
      EndIf
   Next
   
   z=z+2
   PrimList.AddLast(MyType.Create(z))
   
Next

Print "Von 1 bis "+bis*2
Print "Menge der Primzahlen: "+(PrimList.Count()+1)
Print "Zeit : "+(MilliSecs()-time)/1000.0+" sek"
Print "Mem.Anfang: "+memvar+" bytes"
Print "Mem.Ende: "+GCMemAlloced()+" bytes"

While Not KeyHit(KEY_ESCAPE)
Wend

End


Änderungen an dem Code :

-Schrittweite erhöht von z=z+1 auf z=z+2
-Rechnet jetzt ab 3 , da 2 sinnlos ist , weil keine geraden Zahlen überprüft werden (wegen z=z+2)
-Variable counter entfern , da die Menge der Primzahlen der Grösse der Liste entspricht (+1 weil , 1 und 2 nicht in der Liste enthalten sind und zum Schluss noch eine unnötige Zahl reingeschrieben wird)

Was sich geändert hat :

-Rechnet etwas schneller , (AMD 64 4000) bis 100.000.000 mit Print ca. 724sek. , ohne jeglicher Ausgabe ca. 384sek. (Thx Dreamora)
-Das allerbeste ist , die Liste ist jetzt satte 100MB kleiner , sprich ca.185MB wird jetzt an Arbeitsspeicher benötigt , und das allerbeste ist , ich verstehe nicht warum jetzt das so ist , da die alte Liste die gleichen Werte enthalten hat , hmmm (Nochmal Thx an Dreamora)

So , wie ich oben erwähnt habe , bekomme es nicht hin die Liste noch kleiner zu machen (d.h. für die Berechnungen , wird nur die Wurzel der grössten Zahl in der Liste benötigt , sprich noch viel weniger Arbeitsspeicher nötig).
Damit wären Zahlen bis ca. 100.000.000^2*10 ohne grösserer Probleme in akzeptabler Geschwindigkeit(hoffe ist die schnellste Lösung Wink ) zum Ausrechnen möglich.(vorausgesetzt 2GB Arbeitsspeicher).
Wenn jemand eine Idee hat , bitte posten.

MfG

LordArtus

p.s. Aso , 2 und 3 wird nicht ausgegeben , bitte nicht wundern , rechnet trotzdem alles richtig Wink
 

klepto2

BeitragSo, Aug 26, 2007 21:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich habe mal kurz das 'Sieb des Eratosthenes' umgesetzt und was soll ich sagen es ist unbedeutend schneller.
bis 100.000.000 braucht das ganze ca. 8sek ohne ausgabe.

Code: [AUSKLAPPEN]

Const Anzahl = 100000000

Function Prim:Byte[](Zahl:Int = 10000,Ausgabe:Byte = True )
   Local PrimZahlen:Byte[Zahl]
   Local I:Int
   
   For I = 2 To Zahl
      PrimZahlen[I] = False
   Next
   
   Primzahlen[0] = True
   Primzahlen[1] = True
   
   I = 2
   
   While I*I <= Zahl
      If Primzahlen[I] = False Then
         Local J = (I*I)
         While J <=  Zahl
            Primzahlen[j] = True
            J:+i
         Wend
      EndIf
      I:+1
   Wend
   
   If Ausgabe = True Then
      For I = 0 To Zahl
         If Primzahlen[I] = False Then Print I
      Next
   EndIf
   
   Return Primzahlen
End Function


Local T:Int = MilliSecs()
   Prim(Anzahl,False)

Local TT:Int = MilliSecs()

Delay 2000

Local T2:Int = MilliSecs()

   'Prim(Anzahl) 'Auskommentiert da bei 100.000.000 etwas lange ;)
   
Local TT2:Int = MilliSecs()

Print "Range             : " + Anzahl
Print "Zeit ohne Ausgabe : " + (TT-T)
Print "Zeit mit Ausgabe  : " + (TT2-T2)
Matrix Screensaver
Console Modul für BlitzMax
KLPacker Modul für BlitzMax

HomePage : http://www.brsoftware.de.vu

LordArtus

BeitragSo, Aug 26, 2007 22:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Thx klepto2 , mein Fehler , hab mich zu wenig über Primzahlberechnung informiert.
Da ist mein Code totaler Müll Smile
Hast den Code von Wiki kopiert Wink

MfG

LordArtus

p.s. Sieb des Atkin soll noch schneller sein.

LordArtus

BeitragMo, Aug 27, 2007 23:35
Antworten mit Zitat
Benutzer-Profile anzeigen
'Sieb des Atkin' falls es jemanden interresiert:

Code: [AUSKLAPPEN]

limit = 100000000
hFactor = Int(Sqr(limit))-1
Local isprim:Byte[limit]
n:Int=0

time=MilliSecs()

For i=5 To limit
   isprim[i]=False
Next

For i=1 To hFactor

   For j=1 To hFactor
      
      n=4*i*i+j*j
      If (n<=limit And ((n Mod 12=1) Or (n Mod 12=5)))
         isprim[n]=Not isprim[n]
      EndIf
               
      n=3*i*i+j*j
      If (n<=limit And (n Mod 12=7))
         isprim[n]=Not isprim[n]
      EndIf
         
      n=3*i*i-j*j
      If (n<=limit And (i>j) And (n Mod 12=11))
         isprim[n]=Not isprim[n]
      EndIf
      
   Next
   
Next

For i=5 To hFactor
   If isprim[i]=True
      j=i*i
      While j<limit
         isprim[j]=False
         j=j+i*i
      Wend
   EndIf
Next

time=MilliSecs()-time

isprim[1]=True
isprim[2]=True
isprim[3]=True

Rem
For i=1 To limit
   If isprim[i]=True Print i
Next
EndRem

Print "Zeit: "+time+" ms"

While Not KeyHit(KEY_ESCAPE)
Wend


Leider ist es etwas langsamer als die Umsetzung von klepto2.
Für die 100.000.000 braucht es 5127 ms , die Umsetzung von klepto2 3572 ms auf meinen Komp.

MfG

LordArtus
 

Dreamora

BeitragDi, Aug 28, 2007 0:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Versuchs ma indem du isPrim nicht als Byte Array sondern als Int Array implementierst ... heutige Systeme habens net so mit Byte. Sieht gut aus im Source, kommt meistens bei performance checks aber bedeutend mieser raus, weil auf 32bit OS nix mit 8bit adressiert wird sondern mit 32bit und sub adress.

darüber hinaus kannst du von kleptos code vielleicht noch etwas über sinnvolle verwendung von Const etc lernen Smile (const werden beim kompilieren ersetzt, alles was nur const nutzt kann deswegen auch schon beim kompilieren gemacht werden)

Und solange du deine "Optimierungen" in form der Modulos drin hast wird das mit der geschwindigkeit nix fürcht ich. Modulo ist nicht umbedingt die billigste operation ...
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

LordArtus

BeitragDi, Aug 28, 2007 19:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi ,

- "Versuchs ma indem du isPrim nicht als Byte Array sondern als Int Array implementierst ... heutige Systeme habens net so mit Byte" , (Bit wäre natürlich das optimalste) , aber egal , hier der Gegenbeweis was Byte angeht:

Code: [AUSKLAPPEN]

limit=100000000

mem=GCMemAlloced()
Local test:Byte[limit]
mem=GCMemAlloced()-mem

Print "bytemem:"+mem

time=MilliSecs()
For i=0 To limit
   test[i]=False
Next
time=MilliSecs()-time

Print "bytespeed:"+time

Delay 5000

mem1=GCMemAlloced()
Local test1:Int[limit]
mem1=GCMemAlloced()-mem1

Print "intmem:"+mem1

time1=MilliSecs()
For i=0 To limit
   test1[i]=False
Next
time1=MilliSecs()-time1

Print "intspeed:"+time1


- das mit Const sollte jeder wissen Wink
- 'Sieb des Atkin' ohne Modulo umzusetzen wäre nicht so toll Wink
Komischerweise in c++ und c# ist 'Sieb des Atkin' um ca. 30-35% schneller als 'Sieb des Erathostenes'.
Was mir aufgefallen ist , dass das Invertieren in Bmax ziemlich langsam ist , ausserdem könnte Modulo auch langsamer funtzen.

MfG

LordArtus
 

Dreamora

BeitragMi, Aug 29, 2007 18:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Das Problem ist das für Modulo und andere Operationen seit MingW 3.1 drastische Verbesserungen entwickelt wurden.

Deswegen ist C++ und C# soviel schneller.
Das war auch das was mich damals geschockt hat nach dem Wechsel auf den aktuellen MingW, dass Mathe Operationen bis zu 100% schneller liefen und ^ zb nimmer das massive Float Ungenauigkeitsproblem hat trotz allem


Und wenn du das mit Const weisst, warum missachtest du es dann aktiv bei Limit zb Smile
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

LordArtus

BeitragMi, Aug 29, 2007 19:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi ,
Bei den mini-beispiel-test-progrämmchen sehe ich es nicht als notwendig Const zu benutzen (Wird ja hauptsächlich dazu benutzt um nicht aus Versehen eine Variable zu überschreiben bei grösseren Progs..):
-bei meinen Beispielen hat Const überhaupt keinen Einfluss auf die Geschwindigkeit , wenn schon wäre der Vorteil im Nanosek. Bereich (mir gehts fast immer nur um die Geschwindigkeit des Ganzen , nicht darum ob der Code 'schön' aussieht.Ich denke , man kann einiges über einen Menschen erfahren , wenn man seine QuellCodes liest Wink ich=chaotisch korrekt Wink , so auch meine Codes und Ideen Smile) )
-die Codes sind ja ziemlich klein und ausserdem wird Limit nicht so oft verwendet.

MfG

LordArtus

p.s. ok gebe zu , mit programmieren habe ich nicht so viel zu tun , aber hat mich schon immer faszieniert , wie ein Computer funktioniert und um ehrlich zu sein ist es noch immer mein Traum ein eigenes Spiel zu proggen , wahrscheinlich bin ich auch hier gelandet Wink
(Ob die KI irgenwann mal uns überholt ??? naja , so ein Zwischengedanke Wink )
 

Sebe

BeitragDo, Aug 30, 2007 17:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Ob die KI irgenwann mal uns überholt ??? naja , so ein Zwischengedanke


Nein.

LordArtus

BeitragSo, Sep 02, 2007 14:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi ,
Sebe , das klingt , als ob Du ziemlich sicher wärst.
Hast Du keine Begründung dafür ???

MfG

LordArtus
 

Sebe

BeitragSo, Sep 02, 2007 17:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, mal ganz abgesehen von den Speicherplatzproblemen die eine sich selbst weiterentwickelnde, kreative AI hätte würde - da bin ich ziemlich sicher - jemand rechtzeitig den Stecker ziehen.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group