Autor Beitrag
Kroni
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 720

Win 98, Win ME, Win2k, Win XP
D3 Pro
BeitragVerfasst: 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:

ausblenden 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;  //Funktion zum Prüfen auf Primzahl
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)=0then
         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 user profile iconChristian S.: Topic aus Sonstiges verschoben am Fr 26.11.2004 um 16:27
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 26.11.04 19:12 
Hab grad meine eigene Primzahl-Funktion geschrieben:

ausblenden 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 = 2OR (Zahl = 3OR (Zahl = 5then
  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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 720

Win 98, Win ME, Win2k, Win XP
D3 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Fr 26.11.04 20:29 
ausblenden 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 = 2OR (Zahl = 3OR (Zahl = 5then  
  begin  
    Result := 'Prim';  
    Exit;  
  end;  
//  Wurzel := Round(sqrt(Zahl));  //Runden kosten Zeit
  Wurzel := sqrt(Zahl);
  Zaehler := 2;  
  repeat  
//    if frac(Zahl / Zaehler) = 0 then  // frac ist "Arschlangsam"
// in Testläufen war der Test mit frac 10 - 30 mal langsamer als die modulo operation
    if (Zahl mod Zaehler) = 0 then
    begin  
      Result := 'keine Prim';  
      Exit;  
    end;  
    Inc(Zaehler);  
  until Zaehler >= Wurzel;  
  Result := 'Prim';  
end;
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 26.11.04 20:32 
Danke für die Optimierung, aber so darf Zahl nicht Real sein.
st-matze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Fr 26.11.04 20:35 
is mir noch gar nicht aufgefallen, dass zahl real ist. nehmt do INT64
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Fr 26.11.04 21:05 
ausblenden 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 = 2OR (Zahl = 3OR (Zahl = 5then
  begin
    Result := 'Prim';
    Exit;
  end;
  Wurzel := sqrt(Zahl);
  Zaehler := 2;
  Z64 := Trunc(Zahl);  // so kann man real und mod verwenden
  repeat
    if (Z64 mod Zaehler) = 0 then
    begin
      Result := 'keine Prim';
      Exit;
    end;
    Inc(Zaehler);
  until Zaehler > Wurzel;  // da war in der vorherigen variante der fehlerteufel
  Result := 'Prim';
end;
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 26.11.04 21:11 
Es macht einen Unterschied von 0.015 Sekunden, wenn ich leere Zeilen hab.

Und hier das OnClick-Ereignis:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 482

Win XP | Suse 10.1
Delphi 2005 Pers.
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 138

Win 3.11, Win 95, Win 98, Win XP
D7 Ent, D6 Pers, (D5 Pers)
BeitragVerfasst: Fr 26.11.04 21:18 
und die letzte Variante für heute:

ausblenden 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);     //nur ungerade teiler prüfen
  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:

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 720

Win 98, Win ME, Win2k, Win XP
D3 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 26.11.04 21:27 
@st-matze: So wird mir 4 und 4*x als Prim angezeigt.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
  if (Zahl = 2OR (Zahl = 3OR (Zahl = 5then
  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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 720

Win 98, Win ME, Win2k, Win XP
D3 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 26.11.04 21:34 
Ich hab String in Boolean geändert.
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 720

Win 98, Win ME, Win2k, Win XP
D3 Pro
BeitragVerfasst: 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 :evil:
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 26.11.04 21:50 
ausblenden Delphi-Quelltext
1:
Inc(Zaehler, 2)					

Das geht nicht, Zaehler muss um eins erhöht werden.

Jo in einer Stringlist. Die kann man dann auch am Schluß abspeichern.