Autor Beitrag
Born-to-Frag
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 14:00 
Ich überlege seit längerer Zeit wie ich meine Primfaktorzerlegung optimieren kann.. Ich habe schon mehrere ansätze gesehen und auch schon ein paar sachen verbessert. Nur bei zahlen wie 9223372036854775805 wird es dann schon schwieriger, weil sie sehr große Primfaktoren hat.
Also hier mal der Sourcecode:
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:
26:
function IsPrimzahl(Zahl: Int64): Boolean;
begin
  Result := False;
  Teiler := 2;
  while Teiler <= Trunc(Sqrt(1.0 * Zahl)) do begin
        if Zahl mod Teiler = 0 then Exit
        else Inc(Teiler);
  end;
  Result := True;
end;

function PrimFaktorZerlegung (Zahl: Int64): String;
begin
  Teiler := 2;
  Result := '';
  while Zahl > 1 do begin
    if (Teiler > 2and (Teiler mod 2 = 0then Inc(Teiler);
    if IsPrimzahl(Zahl) = True then Teiler := Zahl;
    while (Zahl > 1and (Zahl mod Teiler = 0do begin
      Result := Result + IntToStr(Teiler) + ' * ';
      Zahl := Zahl div Teiler;
    end;
    Inc(Teiler);
  end;
  SetLength(Result, Length(Result) - 3);
end;


Und OnClick:
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:
26:
27:
28:
29:
procedure TForm1.B_BerechneClick(Sender: TObject);
begin
  Z_Begin := GetTickCount;                                                      
  Prim := 'Die Zahl setzt sich aus folgenden Primfaktoren zusammen: ';

  try Zahl := StrToInt64(E_Ausgabe.Text);
  except
    on EConvertError do begin
       Messagebox(Handle, 'Eingabefehler - Zahl zu groß/klein oder ungültige Zeichen!''Fehler', MB_OK or 16);
       E_Ausgabe.SetFocus;
       Exit;
    end;
  end;

  if Zahl < 2 then begin
     Messagebox(Handle, 'Eingabefehler - Zahl muss größer als eins sein.''Fehler', MB_OK or 16);
     Exit;
  end;

  if IsPrimzahl(Zahl) = False then Prim := Prim + PrimFaktorZerlegung(Zahl);

  Z_Ende := GetTickCount;                                                       

  Memo1.Lines.Add(Prim);
  Memo1.Lines.Add('Diese Berechnung dauerte ' + FloatToStr(Z_Ende - Z_Begin) + 'ms!'); 
  Memo1.Lines.Add('');

  E_Ausgabe.SetFocus;
end;


Vielleicht habt ihr ja noch idden.. (Achso, und ich hab den Thread optimierung einer Primzahlfunktion schon gesehen ;))

greetz

EDIT: Bisschen was geändert ;)

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.


Zuletzt bearbeitet von Born-to-Frag am So 20.11.05 17:57, insgesamt 1-mal bearbeitet
AXMD
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: So 20.11.05 15:09 
Ich würde an deiner Stelle die Faktoren in einem Array of Integer speichern - das ist bestimmt um einiges schneller als der String mit dem IntToStr-Zeug.

AXMD
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: So 20.11.05 15:18 
Also ersteinmal würde ich immer um zwei hochzählen und den Teiler zwei, den du dann ja nicht drinhast patchen. Desweiteren würde ich deiner Funktion Isprime deine Variable Teiler übergeben, da aufgrund deines Algorithmus keine Teiler kleiner als deine Variable Teiler möglich sind. Also müssen diese bei Isprime auch nicht überprüft werden. Macht sich besonders bei großen Primzahlen gut.
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 17:20 
JA, aber IntToStr wird eh nur benutzt wenn es ein Primfaktor ist, wenn ich aber so richtig hohe zahlen habe dann dauert das schon mal 2min.. das liegt aber nicht daran. Das mit dem um 2 erhöhen bau ich jetzt gleich noch ein

ich meld mich dann noch einmal

greetz und thx

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
AXMD
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: So 20.11.05 17:22 
user profile iconBorn-to-Frag hat folgendes geschrieben:
JA, aber IntToStr wird eh nur benutzt wenn es ein Primfaktor ist


Kostet trotzdem unnötige Zeit ;)

AXMD
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 17:54 
Ok, also ich hab eure vorschläge jetzt mal mit eingebracht und ich komm bei der zerlegung von 9223372036854775806 auf über 2min.. geht das noch schneller? :)

greetz

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
AXMD
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: So 20.11.05 18:06 
Vielleicht postest du hier vorher erstmal deinen neuen Code ;)

AXMD
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 19:10 
ausblenden volle Höhe 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:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
function IsPrimzahl(Zahl: Int64): Boolean;
begin
  Result := False;
  Teiler := 3;
  if Zahl mod 2 = 0 then Exit;
  while Teiler <= Trunc(Sqrt(1.0 * Zahl)) do begin
        if Zahl mod Teiler = 0 then begin
           Teiler := 3;
           Exit;
        end
        else Inc(Teiler, 2);
  end;
  Result := True;
  Teiler := 3;
end;

function PrimFaktorZerlegung (Zahl: Int64): String;
begin
  Teiler := 3;
  Result := '';
  repeat
    if Zahl mod 2 = 0 then begin
       Result := Result + IntToStr(2) + ' * ';
       Zahl := Zahl div 2;
       if IsPrimzahl(Zahl) = True then Teiler := Zahl;
    end;
  until Zahl mod 2 > 0;

  while Zahl > 1 do begin

    while (Zahl > 1and (Zahl mod Teiler = 0do begin
      Result := Result + IntToStr(Teiler) + ' * ';
      Zahl := Zahl div Teiler;
      if IsPrimzahl(Zahl) = True then Teiler := Zahl;
    end;
    Inc(Teiler, 2);
  end;
  SetLength(Result, Length(Result) - 3);
end;


Mit Array gehts eigendlich nicht schneller.. ok.. vielleicht 0.2Sekunden insgesammt. Aber gibt es keine andere möglichkeit das noch richtig zu verschnellern?

Greetz

EDIT: Funktion Update - Ich teste auch grad noch eine Zahl dann sag ich nochmal wie lange es gedauert hat :)

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.


Zuletzt bearbeitet von Born-to-Frag am So 20.11.05 20:31, insgesamt 1-mal bearbeitet
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: So 20.11.05 19:47 
Dein Algorithmus kocht ja gewissermaßen deine Zahl runter:

nehmen wir an zahl x=2*2*2*3*7*7*13*13. Rechne ich jetzt nicht aus!

Wenn dein Alfo einen Primfaktor findet notiert er ihn und teilt anschließend Zahl x durch diesen Primteiler. Wenn du alle Teiler bis! 5 durchgegangen bist sieht die Restzahl also wie folgt aus: 7*7*13*13. Wenn du jetzt Teiler von 5 auf 7 erhöhst muss dein IsPrimzahl doch nicht noch einmal 2,3 und 5 überprüfen.

Einmal (in deinem Fall) kommt pro erhöhung auf n ca. hab jetzt nicht genau gekuckt n/2 Divisionen in IsPrime hinzu also nach Gauß: 1+2+3+4+5+6...=n*(n+1)/2 folgt in deinem Fall, da du ja jetzt nur noch die ungeraden überprüfst:

Divisionen nach Teiler n : n*(n+1)/4 im Gegensatz zu n/2 für den anderen Fall. Einmal also quadratisch und einmal linear!!!
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 20:02 
user profile iconAllesquarks hat folgendes geschrieben:
Dein Algorithmus kocht ja gewissermaßen deine Zahl runter:

nehmen wir an zahl x=2*2*2*3*7*7*13*13. Rechne ich jetzt nicht aus!

Wenn dein Alfo einen Primfaktor findet notiert er ihn und teilt anschließend Zahl x durch diesen Primteiler. Wenn du alle Teiler bis! 5 durchgegangen bist sieht die Restzahl also wie folgt aus: 7*7*13*13. Wenn du jetzt Teiler von 5 auf 7 erhöhst muss dein IsPrimzahl doch nicht noch einmal 2,3 und 5 überprüfen.


Das er nach dem erhöhen von dem Teiler wieder auf Primzahl überprüft war ein Fehler von mir, hab ich behoben ( Hab ich in der Funktion ober verbessert - er überprüft nur noch auf primzahl nachdem er geteilt hat. Was z.B. seh sinnvoll hier ist: 746782658 er teilt die Zahl durch 2, überprüft dann 373391329 ob es eine Primzahl ist und stellt fest: ja es ist eine! )


user profile iconAllesquarks hat folgendes geschrieben:
Einmal (in deinem Fall) kommt pro erhöhung auf n ca. hab jetzt nicht genau gekuckt n/2 Divisionen in IsPrime hinzu also nach Gauß: 1+2+3+4+5+6...=n*(n+1)/2 folgt in deinem Fall, da du ja jetzt nur noch die ungeraden überprüfst:

Divisionen nach Teiler n : n*(n+1)/4 im Gegensatz zu n/2 für den anderen Fall. Einmal also quadratisch und einmal linear!!!


Wie meinst du das? Kannst du mir das mal an eimen Beispiel zeigen :oops:

Thx 4 help

greetz

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: So 20.11.05 20:19 
Deine Funktion IsPrimzahl funktioniert eigentlich einwandfrei und ist richtig und ist für eine Primzahlüberprüfung genau das richtige. Allerdings nicht in deinem Kontext:

Wie ich oben schon (vielleicht etwas kurz) probiert hab zu zeigen:

Stell dir vor du hast die Zahl x=2*2*2*3*7*7*13*13=bla allerdings ausgerechnet eingegeben bekommen. Dein Programm fängt jetzt an und zwar (gepatcht die zwei) und anschließend die drei. Nun ist die Modulodivision durch 3 Null und du teilst durch drei oder gegebenenfalls mehrmals da das ja auch eine Schleife ist. Sobald diese Schleife terminiert wird die Restzahl nie wieder durch drei teilbar sein genauso ist sie auch nicht mehr durch zwei teilbar. Wenn du jetzt mod 5 abgearbeitet hast gilt gleiches für die fünf. In IsPrimzahl musst du also diese ganzen Zahlen, die du ja schon abgearbeitet hast nicht mehr überprüfen.

Aber meine Rechnung ist ebenfalls fehlerhaft (hatte einen Codeschnipsel übersehen) Meiner meinung kannst du durch diese Verbesserung n*(n+1)/4 Überprüfungen durch n/2 ersetzen allerdings von insgesamt n! in deinem IsPrimzahl (hoffe das stimmt jetzt).

//Edit:

Stell dir ein Primzahlpaar vor da sparst Du bei größeren Zahlen praktisch die Hälfte der Operationen.

Ich persönlich würd IsPrimzahl sowieso in den Mülleimer kloppen, da du in deiner Hauptfunktion sobald Teiler>= Zahl ist, dass Zahl=Primzahl ist


Zuletzt bearbeitet von Allesquarks am So 20.11.05 20:38, insgesamt 1-mal bearbeitet
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 20:35 
user profile iconAllesquarks hat folgendes geschrieben:
Aber meine Rechnung ist ebenfalls fehlerhaft (hatte einen Codeschnipsel übersehen) Meiner meinung kannst du durch diese Verbesserung n*(n+1)/4 Überprüfungen durch n/2 ersetzen allerdings von insgesamt n! in deinem IsPrimzahl (hoffe das stimmt jetzt).


Wo kann ich das ersetzen. Sorry, aber ich hab grad ein Brett vorm Kopf. Wo hab ich denn n*(n+1)/4 Überpfüfungen und wie kann ich diese durch n/2 ersetzen?

Schreib mir doch mal bitte die function.

Ich hab jetzt grad die Zahl 9223372036854775806 zerlegen lassen.. 403 Sekunden. Sehr hohe Primfaktoren...

greetz

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: So 20.11.05 20:43 
//hab oben noch was ersetzt

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:
26:
27:
28:
function PrimFaktorZerlegung (Zahl: Int64): String;  
begin  
  Teiler := 3;  
  Result := '';  
  repeat  
    if Zahl mod 2 = 0 then begin  
       Result := Result + IntToStr(2) + ' * ';  
       Zahl := Zahl div 2;  
       if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
  until Zahl mod 2 > 0;  

 
  while (Teiler<Zahl)AND(Zahl > 1do begin  

 
     while (Teiler<Zahl) AND (Zahl mod Teiler = 0)do begin  
      Result := Result + IntToStr(Teiler) + ' * ';  
      Zahl := Zahl div Teiler;  
      // unnötig if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
    Inc(Teiler, 2);  
  end
 if not(zahl=1then begin
//Primfaktoren.add(zahl);
end;
  SetLength(Result, Length(Result) - 3);  
end;


hab ich nicht getestet aber so würd ich das machen

//jetzt hatt ich aber nen Brett vorm Kopf

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:
26:
function PrimFaktorZerlegung (Zahl: Int64): String;  
begin  
  Teiler := 3;  
  Result := '';  
  repeat  
    if Zahl mod 2 = 0 then begin  
       Result := Result + IntToStr(2) + ' * ';  
       Zahl := Zahl div 2;  
       if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
  until Zahl mod 2 > 0;  

 if zahl >1 then begin
  while (Teiler<=Zahl) do begin  

 
     while (Teiler<=Zahl) AND (Zahl mod Teiler = 0)do begin  
      Result := Result + IntToStr(Teiler) + ' * ';  
      Zahl := Zahl div Teiler;  
      // unnötig if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
    Inc(Teiler, 2);  
  end
end;
   SetLength(Result, Length(Result) - 3);  
end;
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 21:17 
user profile iconAllesquarks hat folgendes geschrieben:
//hab oben noch was ersetzt

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:
26:
27:
28:
function PrimFaktorZerlegung (Zahl: Int64): String;  
begin  
  Teiler := 3;  
  Result := '';  
  repeat  
    if Zahl mod 2 = 0 then begin  
       Result := Result + IntToStr(2) + ' * ';  
       Zahl := Zahl div 2;  
       if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
  until Zahl mod 2 > 0;  

 
  while (Teiler<Zahl)AND(Zahl > 1do begin  

 
     while (Teiler<Zahl) AND (Zahl mod Teiler = 0)do begin  
      Result := Result + IntToStr(Teiler) + ' * ';  
      Zahl := Zahl div Teiler;  
      // unnötig if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
    Inc(Teiler, 2);  
  end
 if not(zahl=1then begin
//Primfaktoren.add(zahl);
end;
  SetLength(Result, Length(Result) - 3);  
end;


hab ich nicht getestet aber so würd ich das machen

//jetzt hatt ich aber nen Brett vorm Kopf

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:
26:
function PrimFaktorZerlegung (Zahl: Int64): String;  
begin  
  Teiler := 3;  
  Result := '';  
  repeat  
    if Zahl mod 2 = 0 then begin  
       Result := Result + IntToStr(2) + ' * ';  
       Zahl := Zahl div 2;  
       if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
  until Zahl mod 2 > 0;  

 if zahl >1 then begin
  while (Teiler<=Zahl) do begin  

 
     while (Teiler<=Zahl) AND (Zahl mod Teiler = 0)do begin  
      Result := Result + IntToStr(Teiler) + ' * ';  
      Zahl := Zahl div Teiler;  
      // unnötig if IsPrimzahl(Zahl) = True then Teiler := Zahl;  
    end;  
    Inc(Teiler, 2);  
  end
end;
   SetLength(Result, Length(Result) - 3);  
end;


Da glaube ich aber das meine funktion wesentlich schneller ist! Dies hat folgenden grund:
IsPrimzahl ist nicht unnötig, denn nehmen wir doch mal an das die Zahl aus folgenden Faktoren besteht: 2*3*2147483647. Dann überprüft er nach dem Teilen durch 3 nicht mehr ob 2147483647 eine Primzahl ist.

das while (Teiler<=Zahl) AND (Zahl mod Teiler = 0) wird bestimmt keinen unterschied machen, aber ich werds nachher noch mal testen, Bin jetzt erts mal 15min weg.

greetz

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: So 20.11.05 21:23 
Zitat:
Da glaube ich aber das meine funktion wesentlich schneller ist! Dies hat folgenden grund:
IsPrimzahl ist nicht unnötig, denn nehmen wir doch mal an das die Zahl aus folgenden Faktoren besteht: 2*3*2147483647. Dann überprüft er nach dem Teilen durch 3 nicht mehr ob 2147483647 eine Primzahl ist.


Da würd ich grad dagengenhalten.

Wenn ich nach der drei Deine Funktion ISPrimzahl aufrufe und der Compi dann dort alle ungeraden Zahlen bis 2147483647 durchgehe, oder dies in der while- Schleife im Hauptprogramm macht nur insofern einen Unterschied, da man dann gerade vieles doppelt macht aber probier es aus
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 21:35 
Du weißt das er bei IsPrimzahl nur bis zu Wurzel prüft? (also ca 46000).. aber ich probiers jetzt aus und schreibs dann hier als edit rein...

greetz

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: So 20.11.05 21:39 
Das mit SQRT kommt noch hinzu allerdings kannste ddas auch in meinen Vorschlag einbringen indem die Abfragen in den Whiles auch nur bis SQRT(Zahl laufen)
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 21:42 
Ich weiß nicht genau was du jetzt meinst, aber ich kann es nicht in die PrimFaktorZerlegung-funktion einbringen, denn 22 besteht z.B. aus den Faktoren 2 und 11, und die Wurzel aus 22 ist ca. 4,69 ;)

greetz

PS: Teste grade deine Funktion mit der Zahl 9223372036854775806. Meine Funktion hat 403 Sekunden gebraucht.

EDIT: WOW!! 221Sekunden. Nicht schlecht!! Hätte ich echt nicht gedacht.. Aber warum? Ich muss mir das nochmal ansehen..
EDIT2: Na gut, es ist je nach zahl verschieden.. wenn ich zu oft nach Primzahl überprüfe spart es irgendwann keine Zeit mehr ein / frisst Zeit

EDIT3: Da sieht man wieder das Problem: bei der Zahl 12884901882 (2*3*2147483647) braucht deine Funktion 36Sekunden, meine 110ms :D

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: So 20.11.05 21:49 
Meiner Meinung nach könnte man das so einbringen:

ausblenden volle Höhe 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:
26:
27:
28:
29:
30:
31:
32:
function PrimFaktorZerlegung (Zahl: Int64): String;    
begin    
  Teiler := 3;    
  Result := '';    
  repeat    
    if Zahl mod 2 = 0 then begin    
       Result := Result + IntToStr(2) + ' * ';    
       Zahl := Zahl div 2;    
       if IsPrimzahl(Zahl) = True then Teiler := Zahl;    
    end;    
  until Zahl mod 2 > 0;    

 
 if zahl >1 then begin  
  while (Teiler<=trunc(SQRT(Zahl))) do begin    

 
   
     while (Teiler<=trunc(SQRT(Zahl)) AND (Zahl mod Teiler = 0)do begin    
      Result := Result + IntToStr(Teiler) + ' * ';    
      Zahl := Zahl div Teiler;    
      // unnötig if IsPrimzahl(Zahl) = True then Teiler := Zahl;    
    end;    
    Inc(Teiler, 2);    
  end;   
end;  
//dann jetzt aber doch 
if not(zahl=1then begin
//zahl ist Primzahl also noch in den String dazuschreiben
end;
   SetLength(Result, Length(Result) - 3);    
end;
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: So 20.11.05 22:10 
Ok, also so ist es jetzt wirklich richtig super: Bei 12884901882 zeigt er die Faktoren auch sofort an, und für 9223372036854775806 braucht er 227Sekunden ( keine verbesserung, aber immer noch besser als meine 403 ;) )

greetz

EDIT: Man könnte noch die Tatsache nutzen, dass alle Primzahlen > 3 mod 6 = 1 oder 5 ergeben.. Denk ich mir bis morgen noch mal was aus

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.