Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Berechnung der kleinsten Zahl mit den Teilern 1-20


Mashalla - Sa 12.07.08 14:30
Titel: Berechnung der kleinsten Zahl mit den Teilern 1-20

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:
function TMainForm.Get_Number: Integer;
var Number_Counter: Integer;
    Divisor_Counter: Integer;
    Continue: Boolean;

begin
  Result := 0;
  Continue := true;

  // Schleife für die Zahlen
  for Number_Counter := 2520 to 2000000000 do
    begin
      // Schleife für die Teiler
      for Divisor_Counter := 2 to 20 do
        begin
          if Continue = true then
            begin
              // prüft auf Teilbarkeit und bricht ab sobald ein Teiler spackt
              if Number_Counter mod Divisor_Counter = 0 then
                Continue := true
              else
                break;
            end;
        end;
      if (Divisor_Counter = 20then
        begin
          Result := Number_Counter;
          exit;
        end;
    end;
end;


Die obige Funktion soll die kleinste Zahl ausgeben, die alle Teiler von 1 bis 20 beinhaltet. Jetzt bin ich allerdings mit der Range schon knapp unter der Integer Grenze angekommen und die Funktion gibt mir immer "0" zurück. Liegt ein Fehler in der Funktion vor oder ist die Zahl wirklich so riesig?

PS: Falls ihr testet, rechnet mit Laufzeiten um 30 Sekunden bei obigen Grenzen :)


Gausi - Sa 12.07.08 14:44

Die Funktion ist falsch. ;-)

Wenn ich mich nicht verrechnet habe, müsste 232.792.560 die gesuchte Zahl sein. Achte mal auf die Warnungen, die der Compiler so ausgibt. ;-)

Und: das kleinste gemeinsame Vielfache lässt sich effizienter ausrechnen.


alzaimar - Sa 12.07.08 14:45

Schalte mal die Compiler-Warnungen an, dann sagt Dir Delphi schon, was faul ist....


nagel - Sa 12.07.08 14:51

user profile iconGausi hat folgendes geschrieben:
Wenn ich mich nicht verrechnet habe, müsste 232.792.560 die gesuchte Zahl sein.

Hab ich auch :) .


Hidden - Sa 12.07.08 15:06

Hi,

Über ihre Primfaktorzerlegung kommst du ja an die Zahl: Sie muss alle Primfaktoren ihrer Teiler enthalten.

Bilde mal die Primfaktorzerlegungen aller Zahlen bis 20. Nun suchst du für jede Primzahl das häufigste Vorkommen und schreibst es heraus; das sind:Somit ist die gesuchte Zahl das Produkt davon und damit (2^4) * (3^3) * 5 * 7 * 11 * 13 * 17 * 19.

Wenn du nun dazu ein Programm schreiben willst, müsstest du das isolieren der Primzahlen nurnoch in einen Algorithmus packen und am Ende das Produkt der Funde bilden.

Edit: Mit dem Windows-Taschenrechner komme ich dann auf Gausis Ergebnis :) .

Edit2: Du solltest dir abgewöhnen, bei jedem begin-Block doppelt(4 Leerzeichen) einzurücken; so kommst du schnell an den Rand und machst den Quelltext unleserlich. Auch würde ich garnicht bei jedem begin zwei Zeilenumbrüche machen:

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 TMainForm.Get_Number: Integer;
var 
  Number_Counter: Integer;
  Divisor_Counter: Integer;
  Continue: Boolean;
begin
  Result := 0;
  Continue := true;

  // Schleife für die Zahlen
  for Number_Counter := 2520 to 2000000000 do begin
    // Schleife für die Teiler
    for Divisor_Counter := 2 to 20 do begin
      if Continue = true then begin
        // prüft auf Teilbarkeit und bricht ab sobald ein Teiler spackt
        if Number_Counter mod Divisor_Counter = 0 then
          Continue := true
        else break;
      end;
    end;
    if (Divisor_Counter = 20then begin
      Result := Number_Counter;
      exit;
    end;
  end;
end;


Zum Highlight: http://www.delphi-forum.de/viewtopic.php?t=83487

mfG,


Mashalla - Sa 12.07.08 15:08

Öhm...die sind eigentlich alle an und der Compiler sagt mir überhaupt nix ?!?

Projekt -> Optionen -> Compiler-Meldungen überall Haken drinne...gibts sonst noch n Menu zum Einstellen?


Gausi - Sa 12.07.08 15:13

Hm, bei mir spuckt der irgendwie auch keine aus...er sollte aber. :gruebel:

Denn: du greifst nach der for-Schleife auf die Schleifenvariable (Divisor_Counter) zu. Das gibt normalerweise eine Warnung, da der Wert nach der Schleife undefiniert ist oder sein kann. Mach mal eine While-Schleife draus.

Außerdem: Welchen Sinn hat Continue? Das ist immer True - da musst du an der Programmlogik noch was tüfteln. ;-)


Mashalla - Sa 12.07.08 16:24

Meh...bin ich vor lauter Hatz mal wieder nicht richtig an die Sache rangegangen *gg* Danke für den Lösungsansatz ;)

@ Gausi:

Joa...müsste wirklich da sein. Ich meine, die Meldung auch am Anfang gehabt zu haben, jedoch wüsst ich jetzt nicht, warum sie nicht mehr da ist :nixweiss:


Reinhard Kern - Sa 12.07.08 21:12

user profile iconHidden hat folgendes geschrieben:
Hi,

Über ihre Primfaktorzerlegung kommst du ja an die Zahl: Sie muss alle Primfaktoren ihrer Teiler enthalten.



Klar, war auch mein erster Gedanke, und bei 1 - 20 geht das in ein paar Minuten mit Taschenrechner oder sogar ganz ohne Hilfe (ein Blatt Papier braucht man schon). Aber eine Schleife, die millardenmal durchlaufen wird, ist einfach viel geiler...

Gruss Reinhard


Timosch - Sa 12.07.08 21:25

user profile iconReinhard Kern hat folgendes geschrieben:
user profile iconHidden hat folgendes geschrieben:
Hi,

Über ihre Primfaktorzerlegung kommst du ja an die Zahl: Sie muss alle Primfaktoren ihrer Teiler enthalten.



Klar, war auch mein erster Gedanke, und bei 1 - 20 geht das in ein paar Minuten mit Taschenrechner oder sogar ganz ohne Hilfe (ein Blatt Papier braucht man schon). Aber eine Schleife, die millardenmal durchlaufen wird, ist einfach viel geiler...

Gruss Reinhard

Mann, du bist wirklich noch ein echter Programmierer von altem Schrot und Korn.


Hidden - Sa 12.07.08 21:53

user profile iconTimosch hat folgendes geschrieben:

Mann, du bist wirklich noch ein echter Programmierer von altem Schrot und Korn.
imho war ziemlich beißender Sarkasmus ;)


Mashalla - So 13.07.08 00:16

Ich danke euch fürs Helfen, evtl komm ich morgen mit dem nächsten Problem vorbei ;)

@ Reinhard:

Gruß übrigens mit "ß", wenn schon groß rausreden (-schreiben), dann bitte richtig...