AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Primfaktorzerlegung läuft viel zu langsam...
Thema durchsuchen
Ansicht
Themen-Optionen

Primfaktorzerlegung läuft viel zu langsam...

Ein Thema von fapsons · begonnen am 28. Feb 2007 · letzter Beitrag vom 3. Mär 2007
Antwort Antwort
Seite 1 von 3  1 23      
fapsons

Registriert seit: 29. Jan 2007
Ort: Berlin
65 Beiträge
 
#1

Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 12:11
Hallo Leute,

habe zur Primfaktorzerlegung hier einen Quelltext gefunden, den ich entsprechend abgeändert habe.
Er läuft allerdings, jedoch viel zu langsam, sodass bei größeren Werten das Programm abstürzt.
Könnt ihr mir da weiterhelfen, was ich evtl. verbessern kann?

Danke
-fapsons-

Delphi-Quellcode:
function Is_Prime(x: int64): Boolean;
var i :Integer;
begin
  result := true;
  for i := 2 to x-1 do
    if x mod i = 0 then result := false
end;



function Get_Prime_Factors(x: Int64): TIntArray;
var i, j, k :Integer;
    r :TIntArray;
begin
  r := TintArray.Create;
  k := 1;
  for i := 2 to x do
  begin
       j := 0;
       while x mod i = 0 do
       begin
          x := x div i;
          inc(j)
       end;

       if j = 1 then
       begin
         r.ints[k] := i;
         k := k + 1;
       end;
  end;
  result := r;
end;
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.861 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 12:26
Delphi-Quellcode:
if x mod i = 0 then
begin
    result := false;
    exit;
end;
Markus Kinzler
  Mit Zitat antworten Zitat
Chris P

Registriert seit: 8. Mär 2004
230 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 12:30
Hi,

also erstens brauchst du nur ungerade Teiler zu testen und zweitens schickt es wenn die for-Schleife
nur bis Wurzel aus x läuft, denn x = Wurzel(x) * Wurzel(x).
  Mit Zitat antworten Zitat
MatWur

Registriert seit: 22. Feb 2007
Ort: Spessart
26 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 12:31
PFZ ist eine komplizierte Sache, wenn sie für grosse Zahlen durchgeführt wird. Die traditionelle Methode des durchtesten wird dabei viel zu langsam. Als erste Optimierung würde ich vorschlagen in deiner Funktion Is_Prime die Testdivisionen auf die ungeraden Zahlen zu beschränken und nur bis SqRt (x) zu testen. Die Testdivisionen sollten später sogar nur die bisher ermittelten Primzahlen umfassen, um nochmal weniger Testdivisionen zu erhalten.
Falls es dir nur um die PFZ einiger bestimmter Zahlen geht empfehle ich dir folgende Seite, sie hat ein Java Applet das sehr gut und schnell mit modernen Methoden faktorisiert:
http://www.alpertron.com.ar/ECM.HTM

Ausserdem empfehle ich dir, dich mit dem "kleinen Fermat'schen Satz" zu befassen (Mathematik), der ist für die Bestimmung von Primzahlen bei grossen Zahlen elementar.

mfg

Matthias
Matthias
Es gibt drei verschiedene Arten von Mathematikern: die, die bis 3 zählen können und die, die das nicht können.
Ich gehöre zur mittleren Gruppe.
  Mit Zitat antworten Zitat
fapsons

Registriert seit: 29. Jan 2007
Ort: Berlin
65 Beiträge
 
#5

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 12:54
Vielen Dank schon mal für eure Hilfe...

Hab es noch nicht versucht mit deinen Verbesserungsvorschlägen MatWur, aber wie setze ich das denn um, dass meine For-Schleife nur ungerade Werte annimmt?

Wahrscheinlich gibt es für mein Problem auch eine viel einfachere Lösung und zwar besteht mein Wert, der zerlegt werden soll aus Faktoren, die jeweils Primzahlen sind.

Also X := 3 * 5 * 7 * 11 oder ähnlich
der höchste Faktor meines Wertes kann max. 31 sein.

Es müsste nur ausgegeben werden, welche einzelnen Faktoren mein Produkt enthält...

Hier nochmal der aktuelle Code mit der ersten Änderung:


Delphi-Quellcode:
function Is_Prime(x: int64): Boolean;
var i :Integer;
begin
  result := true;
  for i := 2 to x-1 do
    if x mod i = 0 then result := false
end;



function Get_Prime_Factors(x: Int64): TIntArray;
var i, j, k :Integer;
    r :TIntArray;
begin
  r := TintArray.Create;
  k := 1;
  for i := 2 to x do
  begin
       j := 0;
       if x mod i = 0 then
       begin
          x := x div i;
          inc(j);
       end;

       if j = 1 then
       begin
         r.ints[k] := i;
         k := k + 1;
       end;
  end;
  result := r;
end;
  Mit Zitat antworten Zitat
Chris P

Registriert seit: 8. Mär 2004
230 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 13:00
So habe ich das gelöst:
Delphi-Quellcode:
function IsPrime(const Value: Cardinal): Boolean;
var
   t: Cardinal;
begin
   if (Value = 2) then
   begin
      Result := TRUE;
      Exit;
   end;

   if (Value < 2) or (Value mod 2 = 0) then
   begin
      Result := FALSE;
      Exit;
   end;

   t := 3;
   while (t * t <= Value) do
   begin
      if (Value mod t = 0) then
      begin
         Result := FALSE;
         Exit;
      end
      else
         t := t + 2;
   end;
   Result := TRUE;
end;
// -----------------------------------------------------------------------------
function Factorize(const V: Cardinal): TFactors;
var
   t, x, Count: Cardinal;
begin
   t := 2;
   x := V;

   Count := 0;
   SetLength(Result, 0);

   while (t <= x) do
   begin
      if (x mod t = 0) then
      begin
         Count := Count + 1;
         SetLength(Result, Count);
         Result[Count - 1] := t;
         x := x div t;
         t := 2;
      end
      else
         t := t + 1;
   end;
end;
  Mit Zitat antworten Zitat
MatWur

Registriert seit: 22. Feb 2007
Ort: Spessart
26 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 13:11
ich wollte gerade anfangen, aber Chris P hat schon eine brauchbare Lösung abgeliefert.
Zuerst wird getestet ob die Zahl gleich 2 ist, wenn ja prim und raus.
Dann wird getestet ob es 0,1 oder eine gerade Zahl>2 ist, wenn ja nicht prim und raus.
Dann werden beginnend mit t=3 die ungeraden Zahlen abgetestet und falls ein Faktor gefunden wird -> nicht prim und raus.

Wenn bei deinen Zahlen tatsächlich nur Primzahlen bis 31 vorkommen kannst du den Schritt
while (t * t <= Value) do
ersetzen durch
while (t <= 31) do, damit kannst du bei grossen Zahlen noch einmal Zeit sparen.

Das er den Typ Cardinal statt wie du den Typ Int64 genommen hat sollte hoffentlich kein Problem sein. Weenn doch, bitte rückfragen.

mfg

Matthias

Edit: PS

eine for Schleife für ungerade Zahlen erhälst du folgendermaßen:
Delphi-Quellcode:
for i := 0 to 19 do begin
  n := 2*i+1;
  {rechnen mit n} end;
in dieser Schleife hat n nacheinander die Werte 1, 3, 5, ..., 37, 39
Matthias
Es gibt drei verschiedene Arten von Mathematikern: die, die bis 3 zählen können und die, die das nicht können.
Ich gehöre zur mittleren Gruppe.
  Mit Zitat antworten Zitat
Chris P

Registriert seit: 8. Mär 2004
230 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 13:18
@MatWur: Danke für die ergänzende Erklärung
  Mit Zitat antworten Zitat
Benutzerbild von Nikolas
Nikolas

Registriert seit: 28. Jul 2003
1.528 Beiträge
 
Delphi 2005 Personal
 
#9

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 13:21
Ich würde diese Schreibweise bevorzugen:
Delphi-Quellcode:
for i:=1 to floor(sqrt(x)) do
 if (x mod (2*i+1)) = 0 then
 begin
   result:= false;
   exit;
 end;
Macht eigentlich nichts anderes, müsste aber schneller sein, da nicht bei jedem Durchlauf t*t mit x verglichen werden muss, sondern die maximale Anzahl der Durchläufe schon von Anfang an feststeht.
Und jemand mit einem etwas geschulten mathematischen Blick erkennst den Ausdruck 2*i+1 sofort als Reihe der ungeraden Zahlen.
Ich glaube schon gelesen zu haben, dass der Compiler aufsteigende Schleifen auch gerne durch downtoschleifen ersetzt, da anscheinend das prüfen auf Variable=0 einfacher ist als Variable=SonstiergWert. Ist hier zwar nicht direkt der Fall, da im niedrigsten Fall noch auf i=1 getestet wird, aber wär mal einen Gedanken wert, da die aufsteigende Schleife wahrscheinlich früher abbricht, als die absteigende.
Erwarte das Beste und bereite dich auf das Schlimmste vor.
  Mit Zitat antworten Zitat
Chris P

Registriert seit: 8. Mär 2004
230 Beiträge
 
Delphi 7 Enterprise
 
#10

Re: Primfaktorzerlegung läuft viel zu langsam...

  Alt 28. Feb 2007, 13:31
Das mag ja sein nur du rufst in jedem Schleifendurchlauf floor(...) und sqrt(...) auf.
Außerdem ist sqrt ungenau da es mit Fließkommazahlen arbeitet.

Das hat man bei bei meiner Lösung nicht.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz