Autor |
Beitrag |
Kroni
Beiträge: 720
Win 98, Win ME, Win2k, Win XP
D3 Pro
|
Verfasst: Fr 26.11.04 17:24
Hallo,
könntet ihr vielleicht mal einen Blick auf meine Funktion zum Testen, ob eine Zahl eine Primzahl ist werfen, ob das Testen vielleicht noch etwas schneller geht?
Hier einmal die Funktion:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| function prim(zahl:integer):boolean; var teiler:integer; wurzel:extended; begin teiler:=1; result:=true; wurzel:=sqrt(zahl);
while ((teiler<=wurzel) and (teiler<>(zahl-1)) and result) do begin if (odd(zahl) or (zahl=2)) then begin teiler:=teiler+1; if ((zahl mod teiler)=0) then result:=false; end else result:=false; end; end; |
Also ist ja schonmal, dass der nur die Ungeraden Zahlen auf Primzahl kontrolliert....und ansonsten weiß ich nicht genau, ob es schneller ist, die Schleife nur dann zu beginnen, wenn das ungerade ist, oder das in der Schleife abzufragen.
Ansonsten wird ja schon wurzel also sqrt(zahl) schon einmal ausgerechnet, das erspart ja auch schon zeit...
ansonsten wäre es sinnvoller, mit einer anderen Boolschen Variablen zu rechnen, und dann das Ergebnis dem Result zuzuweisen, oder direkt so wie ich es geamcht habe, mit Result zu rechnen?
Danke für eure Antworten Moderiert von Christian S.: Topic aus Sonstiges verschoben am Fr 26.11.2004 um 16:27
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 19:12
Hab grad meine eigene Primzahl-Funktion geschrieben:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| function Prim (Zahl: Real): String; var Zaehler: Integer; Wurzel: Integer; begin if (Zahl = 2) OR (Zahl = 3) OR (Zahl = 5) then begin Result := 'Prim'; Exit; end;
Wurzel := Round(sqrt(Zahl)); Zaehler := 2;
repeat if frac(Zahl / Zaehler) = 0 then begin Result := 'keine Prim'; Exit; end; inc(Zaehler); until Zaehler = Wurzel;
Result := 'Prim'; end; |
Bin grad am testen der Geschwindigkeit.
EDIT: Etwa 1000 Zahlen pro Sekunde. Wäre das immer gleich schnell, wären nach 1 Minute 60000 Zahlen überprüft.
EDIT2: 63 Sekunden für 60000 Zahlen. Ich mach jetzt mal die Application.ProcessMessages nur noch alle 500 Zahlen (das heißt er muss jetzt dafür jedes prüfen, ob es 500 sind).
EDIT3: Mh... bringt nix, da man Application.ProcessMessages gar nicht braucht. Ich lasse jetzt nur noch Zahlen anzeigen, die Primzahlen sind (von 2 bis 60000).
EDIT4: 6 Sekunden.
Die größe gefundene Primzahl ist 224,036,583-1. Die Zahl wurde durch das Projekt GIMPS gefunden. Das Projekt GIMPS nutzt wie SETI die Leerlaufzeit der Computer, auf denen GIMPS installiert ist. Warum machen wir nicht auch so ein Projekt?
EDIT5: Für 6.000.000 Zahlen werden 5 Minuten und 2 Sekunden benötigt (wenn ich zu der Zeit etwas anderes mache). Da ich jetzt essen gehe, lasse ich 15 Millionen Zahlen prüfen.
|
|
Kroni
Beiträge: 720
Win 98, Win ME, Win2k, Win XP
D3 Pro
|
Verfasst: Fr 26.11.04 20:14
also gehts du im prinzip alle zaheln von eins bis was weiß ich durch, und guckst, ob die Primzahlen sind oder??
Na ja, dein Programm erinnert mich n bissl an deines*g* aber was mir gar nicht gefällt ist der EXIT Befehl..........Mein Lehrer würde mich dafür töten.
Aber gut, dass du frac benutzt, weil MOD ist ja ends langsam soweit ich weiß. ich gehe jetzt auch essen, bis später =)
|
|
st-matze
Beiträge: 138
Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
|
Verfasst: Fr 26.11.04 20:29
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| function Prim (Zahl: Real): String; var Zaehler: Integer; Wurzel: double; begin if (Zahl = 2) OR (Zahl = 3) OR (Zahl = 5) then begin Result := 'Prim'; Exit; end; Wurzel := sqrt(Zahl); Zaehler := 2; repeat if (Zahl mod Zaehler) = 0 then begin Result := 'keine Prim'; Exit; end; Inc(Zaehler); until Zaehler >= Wurzel; Result := 'Prim'; end; |
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 20:32
Danke für die Optimierung, aber so darf Zahl nicht Real sein.
|
|
st-matze
Beiträge: 138
Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
|
Verfasst: Fr 26.11.04 20:35
is mir noch gar nicht aufgefallen, dass zahl real ist. nehmt do INT64
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 20:39
Da geht Wurzelziehen nicht.
EDIT: Oh, du hast recht. Durch das weglassen von Round, kommen weniger Zahlen (und hoffentlich nur Primzahlen) und es sieht nur so aus, als wär es langsamer.
EDIT2: Wenn Round weg ist, sinds keine Primzahlen mehr.
EDIT3: Round muss wieder hin, habs grad geprüft und dann ist mod um 156 Millisekunden schneller bei 10-100.000.
|
|
st-matze
Beiträge: 138
Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
|
Verfasst: Fr 26.11.04 21:05
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| function Prim (Zahl: Real): String; var Zaehler: Integer; Wurzel: double; Z64: Int64; begin if (Zahl = 2) OR (Zahl = 3) OR (Zahl = 5) then begin Result := 'Prim'; Exit; end; Wurzel := sqrt(Zahl); Zaehler := 2; Z64 := Trunc(Zahl); repeat if (Z64 mod Zaehler) = 0 then begin Result := 'keine Prim'; Exit; end; Inc(Zaehler); until Zaehler > Wurzel; Result := 'Prim'; end; |
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 21:11
Es macht einen Unterschied von 0.015 Sekunden, wenn ich leere Zeilen hab.
Und hier das OnClick-Ereignis:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.StartButClick(Sender: TObject); var Start, Ende: Real; X: Integer; Erg: String; begin Start := GetTickCount;
for X := StrToInt(VonEdit.Text) to StrToInt(BisEdit.Text) do begin Erg := Prim(X); if Prim(X) = 'Prim' then PrimMemo.Lines.Add(IntToStr(X) + ': Prim'); end;
Ende := GetTickCount; DauerLab.Caption := 'Diese Überprüfung hat ' + FloatToStr((Ende - Start) / 1000) + ' Sekunden gedauert.' end; |
Zuletzt bearbeitet von GTA-Place am Fr 26.11.04 21:17, insgesamt 2-mal bearbeitet
|
|
sourcehunter
Beiträge: 482
Win XP | Suse 10.1
Delphi 2005 Pers.
|
Verfasst: Fr 26.11.04 21:13
Ich weiß nicht, wieviel es hilft, aber du könntest noch auf Teilbarkeit durch kleine Primzahlen testen, so zwischen 1..10.
_________________ Linux und OpenSource rulez!
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 21:17
Das wird ja eigentlich gemacht, da immer von 2 bis zur Zahl geprüft wird.
PS: Oben hab ich noch das OnClick-Ereignis gepostet.
|
|
st-matze
Beiträge: 138
Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
|
Verfasst: Fr 26.11.04 21:18
und die letzte Variante für heute:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| function Prim (Zahl: Real): String; var Zaehler: Integer; Wurzel: double; Z64: Int64; begin Z64 := Trunc(Zahl); if Odd(Z64) then begin Result := 'Prim'; Exit; end; Wurzel := sqrt(Zahl); Zaehler := 3; repeat if (Z64 mod Zaehler) = 0 then begin Result := 'keine Prim'; Exit; end; Inc(Zaehler,2); until (Zaehler > Wurzel); Result := 'Prim'; end; |
Anmerkung:
stringzuweisungen dauern auch sehr lange, weil bei jeder zuweisung neuer speicher belegt wird.
wie wärs stattdessen mit:
Delphi-Quelltext 1: 2: 3: 4: 5:
| function Prim (Zahl: Real): boolean; begin ... Result:= true; end; |
Ich kenne ja euer rahmenprogramm nicht, ob dort der string unbeding nötig ist.
Frage:
speichert ihr eure primzahlen eigentlich?!?
Edit: Dann könnt ihr nähmlich immer nur die teilbarkeit durch die bereits gefundenen zahlen prüfen.
Zuletzt bearbeitet von st-matze am Fr 26.11.04 21:20, insgesamt 1-mal bearbeitet
|
|
Kroni
Beiträge: 720
Win 98, Win ME, Win2k, Win XP
D3 Pro
|
Verfasst: Fr 26.11.04 21:19
macht doch anstatt exit einfach mal mit eine Abbruchbedingung in die Schleife...würd ich schöner finden.
ansonsten klingt das recht logisch und ist ja genauso aufgebaut wie mienes......ist denn eigentlich zahl mod 2 schneller als odd(zahl)???
wobei ich mal auch meine gelesen z7u haben, dass mod so sehr langsam sein soll....ist trunc schneller???
das endet hier ja in nem Contest, wer hat am schnellsten die meisten Primzahlen*ggg*
mit Int64 kann ich leider nicht arbeiten, da ich Delphi3 Pro habe*heul*
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 21:22
1. Wieso "eure"? "deine" muss es heißen, oder meinst du noch das vom Thread-Ersteller?
2. Hab mir gedacht, wenns ein gr. Projekt wird, wird ein Computer mit dem Prog. drauf, z.B. die Zahlen zw. 100 und 200 überprüfen und ein andere Computer, die Zahlen zw. 200 u. 300 überprüfen und dann an den Server schicken, das Ergebnis.
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 21:27
@st-matze: So wird mir 4 und 4*x als Prim angezeigt.
Delphi-Quelltext 1: 2: 3: 4: 5:
| if (Zahl = 2) OR (Zahl = 3) OR (Zahl = 5) then begin Result := 'Prim'; Exit; end; |
Das hab ich verwendet, weil "Wurzel aus 2, 3 und 5 < Zaehler". 5 geht jetzt glaub, da Round fehlt.
Zuletzt bearbeitet von GTA-Place am Fr 26.11.04 21:31, insgesamt 1-mal bearbeitet
|
|
Kroni
Beiträge: 720
Win 98, Win ME, Win2k, Win XP
D3 Pro
|
Verfasst: Fr 26.11.04 21:30
also.....@st-matze
guck dir mal mein Primzahlprogramm an.....bzw die Funktion...da war mein Rückgabewert auch ein Boolean....ist für mich eigentlich Logischer zu sagen,m ob Zahl x true or false ist.....finde ich...
Ansonste hatte ich eigentlich vor, die Ausgabe nich in die Schleife einzubauen, wo ich meinetwegn von 1 bis 1000 gehe um zu gucken, welche Zahlen davon Primzahl sind, weil das total langsam ist => Grafik in Delphi ist wirklich verdammt langsam.
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 21:34
Ich hab String in Boolean geändert.
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 21:43
Ich lass jetzt nur noch die neuste gefundene Primzahl anzeigen.
EDIT: Der zeigt ja gar keine Primzahlen an:
Zitat: | 83: Prim
85: Prim
87: Prim
89: Prim
91: Prim
93: Prim
95: Prim
97: Prim
99: Prim |
|
|
Kroni
Beiträge: 720
Win 98, Win ME, Win2k, Win XP
D3 Pro
|
Verfasst: Fr 26.11.04 21:46
wie wärs denn, wenn wir n dynamische array nehmen und die primzahlen da alle abspeichern? oder mit einer TStringList oder so??
dynamisches array wollte ich ja eigentlich auch schon machen aba mit delphi 3 gehts alles nich
|
|
GTA-Place
Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Fr 26.11.04 21:50
Delphi-Quelltext
Das geht nicht, Zaehler muss um eins erhöht werden.
Jo in einer Stringlist. Die kann man dann auch am Schluß abspeichern.
|
|
|