AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Erstellung einer Schleife mit drei Überprüfungen
Thema durchsuchen
Ansicht
Themen-Optionen

Erstellung einer Schleife mit drei Überprüfungen

Ein Thema von Mo53 · begonnen am 23. Mai 2021 · letzter Beitrag vom 24. Mai 2021
Antwort Antwort
Seite 3 von 3     123   
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#21

AW: Erstellung einer Schleife mit drei Überprüfungen

  Alt 24. Mai 2021, 21:42
@Michael II Es tut mir leid für meine Dummheit aber ich verstehe deinen Lösungsvorschlag für die Primzahlen nach mehrmaligem durchlesen immer noch nicht.
Könntest du den Lösungsansatz vielleicht step by step erklären.
Für zahl = 2 gibst du prim aus.

Du fragt wegen allen anderen Primzahlen. Hier Code.

Delphi-Quellcode:
var teiler, pruefebis, zahl : integer;
    ist_prim : boolean;
....

  zahl := 91;

  ist_prim := true;
  teiler := 3;
  pruefebis := trunc(sqrt(zahl));
  while ist_prim and ( teiler <= pruefebis ) do
  begin
    ist_prim := zahl mod teiler <> 0;
    inc( teiler, 2 ); // teiler := teiler + 2;
  end;
Lade den Code in der IDE und steppe durch wie TurboMagic geschrieben hat.

Zum Code:

Wir nehmen zuerst ist_prim:= TRUE an und werden vielleicht später (in der while Schleife) das Gegenteil beweisen.

zahl ist im Beispiel 91.
Du weisst, dass es einen echten Teiler von 91 <= sqrt(91) geben muss, wenn 91 nicht prim ist.
Wir prüfen also für teiler mit den Werten 3,5,...9, ob zahl durch teiler teilbar ist.
Wenn dem so ist, wird ist_prim in der while Schleife FALSE. => Die Schleife wird wegen der Abbruchbedingung (while ist_prim and ( teiler <= pruefebis ) do) verlassen.

Am Ende der while Schleife ist ist_prim TRUE, wenn zahl eine Primzahl ist, sonst FALSE



Da ihr wahrscheinlich keine "function" benutzen dürft, ist die Aufgabe mit den Primzahlzwillingen etwas aufwändig [und ohne die Verwendung von "function" vielleicht auch ein wenig nutzlos ].
Michael Gasser

Geändert von Michael II (24. Mai 2021 um 23:03 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.034 Beiträge
 
Delphi 12 Athens
 
#22

AW: Erstellung einer Schleife mit drei Überprüfungen

  Alt 24. Mai 2021, 21:55
F7 ist, Dank der bescheuert standardrdmäßig aktiven Option "Debug-DCUs", seit zuvielen Jahren nicht mehr so toll.

also F8

oder in den Projektoptionen die Debug-DCUs deaktivieren,
es sei denn jemandem macht es Spaß, wenn er die VCL/RTL/System-Units ebenfalls debuggen will.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#23

AW: Erstellung einer Schleife mit drei Überprüfungen

  Alt 24. Mai 2021, 22:03
@Michael II ist es möglich das ganze auch in einer repeat schleife zu verpacken?
Wie mach man das jetzt mit dem Primzahlzwilling, da istprime ja boolean ist klappt es in der nächsten überprüfung nichtmehr mit zahl+2 = istprime
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#24

AW: Erstellung einer Schleife mit drei Überprüfungen

  Alt 24. Mai 2021, 22:22
Dieser Code gibt dir aus, ob eine Zahl gerade ist, ob fibo, ob prim, ob zwillingsprim.

Da du sicher keine function istprim(zahl) verwenden darfst, merken wir uns halt in zwei booleschen Variablen, ob die letzte ungerade Zahl (zahl-2) prim war (letzte_warprim) und ob die nächste ungerade (zahl+2) es sein wird (naechste_istprim). So müssen wir jede zahl nur einmal auf prim prüfen.

Die "Spezialwerte" 0,1,2 geben wir direkt aus. (Man müsste den Code durch diese drei "Sonderfälle" aufblähen. - Tun wir nicht.)

Was macht das Programm?

Fibo: Für fibo berechnen wir am Anfang die kleinste Fibo-Zahl f, welche >= LOWER_BORDER ist. Dann geht's ab in die while Schleife. Sobald zahl=f wissen wir "fibo!". Wir setzen im fibo Fall istfibo:=TRUE und müssen das nächste Glied f der Fibofolge berechnen. Bei der Berechnung von f=f[n] greifen wir auf die gespeicherten Werte von f[n-1] und f[n-2] zurück.

Gerade: istgerade := zahl mod 2 = 0; und das war's bereits.

Primzahlen und deren Zwillinge: Für Zahlen, welche ungerade sind, prüfen wir auf prim. Wir prüfen dabei nicht die aktuelle Zahl, sondern "zahl+2". Grund: Wir müssen für die Bewertung "zahl ist Zwilling oder nicht" wissen, ob die nächste ungerade Zahl "zahl+2" prim ist. Wir speichern in naechste_istprim ab, ob "zahl+2" prim ist. In letzte_warprim merken wir uns, ob die letzte ungerade Zahl prim war. In diese_istprim steht, ob zahl prim ist. diese_istprim berechnen wir dabei nicht via Faktorzerlegung von zahl: Wir wissen ja dank letzte_warprim, ob zahl prim ist oder nicht. "zahl" ist Teil eines Primzahlzwillings, wenn
primzwilling := diese_istprim and ( letzte_warprim or naechste_istprim );

Fertig - Viel Spass beim Denken.


Delphi-Quellcode:
var teiler, sqrt_n, naechste, zahl, fn_1, fn_2, f : int64;
    primzwilling, istfibo, istgerade, letzte_warprim, naechste_istprim, diese_istprim : boolean;

const
  LOWER_BORDER = 0;
  UPPER_BORDER = 50;

begin
  if ( LOWER_BORDER = 0 ) then writeln( '0 even: TRUE fib: TRUE prim: FALSE twinprim: FALSE' );
  if ( LOWER_BORDER <= 1 ) and ( 1 <= UPPER_BORDER ) then writeln( '1 even: FALSE fib: TRUE prim: FALSE twinprim: FALSE' );
  if ( LOWER_BORDER <= 2 ) and ( 2 <= UPPER_BORDER ) then writeln( '2 even: TRUE fib: TRUE prim: FALSE twinprim: FALSE' );
  if ( LOWER_BORDER mod 2 = 0 ) then zahl := LOWER_BORDER-3 else zahl := LOWER_BORDER-4;

  if ( zahl < 3 ) then
  begin
    zahl := 3;
    naechste_istprim := true; // 3 ist Primzahl
  end;

  fn_1 := 1;
  fn_2 := 1;
  f := 2;
  while ( f < zahl ) do // berechne die kleinste Fibo-Zahl f, welche >= LOWER_BORDER
  begin
    f := fn_1 + fn_2;
    fn_2 := fn_1;
    fn_1 := f;
  end;

  while ( zahl <= UPPER_BORDER ) do
  begin
    istfibo := f = zahl;
    if istfibo then
    begin // die nächste Fibozahl wird berechnet
        f := fn_1 + fn_2;
        fn_2 := fn_1;
        fn_1 := f;
    end;

    istgerade := zahl mod 2 = 0;

    if not istgerade then
    begin
      diese_istprim := naechste_istprim; // in durchlauf "zahl-2" haben wir berechnet, ob "zahl" prim ist
      naechste := zahl + 2; // die nächste ungerade zahl nach "zahl" auf prim prüfen
      sqrt_n := trunc(sqrt(naechste)); // bis zu diesem wert suchen wir nach möglichen teilern von naechste
      teiler := 3;
      naechste_istprim := true; // wir nehmen mal an, "naechste" sei prim
      while naechste_istprim and ( teiler <= sqrt_n ) do
      begin // und prüfen, ob dem so ist
        naechste_istprim := naechste mod teiler <> 0;
        inc( teiler, 2 );
      end;
      // naechste_istprim = true, wenn naechste=zahl+2 prim ist
      // wir prüfen, ob "zahl" zu einem Zwilling gehört
      primzwilling := diese_istprim and ( letzte_warprim or naechste_istprim );
      letzte_warprim := diese_istprim; // wir merken uns für runde "zahl+2", ob "zahl" prim ist
    end
    else
    begin
      diese_istprim := false; // "zahl" ist gerade also nicht prim
      primzwilling := false; // ..und damit auch nicht Teil eines Zwillings
    end;

    if ( zahl >= LOWER_BORDER ) then // Ausgabe
    writeln(zahl, ' even: ', istgerade, ' fib: ', istfibo, ' prim: ', diese_istprim, ' twinprim: ', primzwilling );
    inc( zahl );
  end;

  readln;
Michael Gasser

Geändert von Michael II (24. Mai 2021 um 23:06 Uhr)
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#25

AW: Erstellung einer Schleife mit drei Überprüfungen

  Alt 24. Mai 2021, 23:09
Das sieht sehr gut aus, ich habe in der zwischenzeit auch meinen code bearbeitet, jedoch wird auf einmal nur bis 1 ausgegeben.
Bevor ich die zwei neuen repeat schleifen eingefügt hab hat es bis 50 geklappt, siehst du vielleicht woran es liegt.

Delphi-Quellcode:
program ueb04;

{$APPTYPE CONSOLE}
{$R+,Q+,X-}

uses
  System.SysUtils;

const
  LOWER_BORDER = 0;
  UPPER_BORDER = 50;

var
  even: boolean;
  fib: boolean;
  twinprim: boolean;
  NextPrim: boolean;
  PrevPrim: boolean;
  zahl: integer;
  Primzahl: boolean;
  teiler: integer;
  uebrig: integer;
  a: integer;
  b: integer;
  c: integer;

begin
  for zahl := LOWER_BORDER to UPPER_BORDER do
  begin
    even := false;
    fib := false;
    twinprim := false;

    if zahl > 1 then
    begin
      // Überprüfung ob gerade:
      even := (zahl mod 2 = 0);

      // Überprüfung ob Primzahl:
      teiler := 1;
      repeat
        teiler := teiler + 1;
        uebrig := zahl mod teiler;
      until (uebrig = 0);

      Primzahl := (zahl = teiler);
    end;

    if Primzahl then
    begin
      Teiler:= 1;
      repeat
        teiler := teiler + 1;
        uebrig := zahl + 2 mod teiler;
      until (uebrig = 0);
      NextPrim := (zahl + 2) = teiler;
    end;

    if Primzahl and (zahl > 3) then
    begin
      Teiler:= 1;
      repeat
        teiler := teiler + 1;
        uebrig := zahl - 2 mod teiler;
      until (uebrig = 0);
      PrevPrim := (zahl - 2) = teiler;
    end;

    twinprim := Primzahl and (NextPrim or PrevPrim);

    // Überprüfung ob Teil der Fibonacci-Folge:
    a := 0;
    b := 1;
    c := 0;
    while (a < zahl) and not fib do
    begin
      c := a + b;
      a := b;
      b := c;
      fib := c = zahl;
    end;
    WriteLn(zahl, ' even: ', even, ' fib: ', fib, ' twinprim: ', twinprim);
  end;
  readln;

end.
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#26

AW: Erstellung einer Schleife mit drei Überprüfungen

  Alt 24. Mai 2021, 23:58
uebrig := zahl - 2 mod teiler; ist nicht das, was du willst.

mod wird vor +*-/ ausgewertet.

Was du willst ist
uebrig := ( zahl - 2 ) mod teiler;

In deinem Code berechnest du in jeder Runde drei Mal, ob eine Zahl (du rechnest für zahl-2, zahl und zahl+2) prim ist. Wie du gesehen hast geht es auch mit einer Berechnung pro Runde: Du könntest dir jeweils prim oder nicht für zahl und zahl+2 merken. In der nächsten "ungeraden zahl Runde" kannst du dann auf diese Werte zurückgreifen und musst nur für "zahl+2" rechnen.

Wie besprochen: Ausser 2 ist keine Primzahl gerade. Überprüfe also nur ungerade teiler.
teiler := teiler + 2;

Wie besprochen: Prüfe nur für ungerade Teiler von 3 bis sqrt(zahl).

Delphi-Quellcode:
  ist_prim := true;
  teiler := 3;
  pruefebis := trunc(sqrt(zahl));
  repeat
    ist_prim := zahl mod teiler <> 0;
    inc( teiler, 2 );
  until not ist_prim or ( teiler > pruefebis );
Fibo müsstest du nicht für jede Zahl immer neu berechnen. Es reicht, wenn du dir immer die nächste Fibo-Zahl f > zahl merkst und dann in jeder Runde auf f=zahl prüfst.
Das spielt hier keine grosse Rolle - aber Effizienz in Schleifen ist wichtig .
Michael Gasser

Geändert von Michael II (25. Mai 2021 um 00:16 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 11:53 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