Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Übergabe von Zahlen an Prozedur (https://www.delphipraxis.net/174573-uebergabe-von-zahlen-prozedur.html)

Crattely 29. Apr 2013 18:33

Delphi-Version: 5

Übergabe von Zahlen an Prozedur
 
Hallo,
wir sollen für die Schule ein Programm schreiben, das eine komplette Funktionsanalyse durchführt.
Nun bin ich schon recht weit, hänge allerdings an einer Stelle.
Ich habe mir eine Prozedur geschrieben, die die Nullstellen einer Funktion 5. Grades berechnet.
Diese funktioniert nach dem Schema a*x^5+b*x^4 usw, dann wird a,b,c,d,e,f übergeben.
Nun möchte ich, um die Extrempunkte zu berechnen, anstelle von a Null übergeben, da ich dafür die Nullstellen der ersten Ableitung benötige und damit nach dem Ableiten kein^x^5 mehr existiert.
Wenn ich nun die Prozedur:
procedure Nullstellen(var a,b,c,d,e,f:real; var NST1,NST2,NST3,NST4,NST5:real; var NST6:string; var Anzahl_NST:integer);

mit den eingelesenen Variablen aufrufe, funktioniert alles.
Wenn ich aber nun mit Nullstellen(0,5*a,4*b...) aufrufe bekomme ich den Fehler:
Die Typen der formalen und tatsächlichen Var-Parameter müssen übereinstimmen...
Woran liegt das ? Gilt die Null nicht als Real-Zahl ?
MfG

Sir Rufo 29. Apr 2013 18:42

AW: Übergabe von Zahlen an Prozedur
 
Wenn du
Delphi-Quellcode:
var
vor einen Parameter schreibst, dann musst du den Parameter auch als Variable übergeben.

Allerdings ist das hierfür wohl eh Quark, also definiere die Parameter a..f nicht als
Delphi-Quellcode:
var
sondern einfach nur so oder meinetwegen auch als
Delphi-Quellcode:
const
Delphi-Quellcode:
procedure Nullstellen(const a,b,c,d,e,f:real; var NST1,NST2,NST3,NST4,NST5:real; var NST6:string; var Anzahl_NST:integer);
begin
  ...
end;
BTW: Die Nullstellen kannst du auch als Array zurückgeben, dann sparst du dir auch das
Delphi-Quellcode:
Anzahl_NST
Und wofür ist denn
Delphi-Quellcode:
NST6 : string
?

guinnes 29. Apr 2013 18:45

AW: Übergabe von Zahlen an Prozedur
 
Du hst die Variablen als VAR deklariert, demnach mußt du auch Variablen übergeben. Jede Zahl, die du da reinschreibst wird als Konstante angesehen und erzeugt einen Fehler. Wenn du die Parameter innerhalb der Funktion nicht änderst, lass in der Deklaration das Var weg

Mathematiker 29. Apr 2013 19:08

AW: Übergabe von Zahlen an Prozedur
 
Hallo,
Zitat:

Zitat von Crattely (Beitrag 1213446)
Ich habe mir eine Prozedur geschrieben, die die Nullstellen einer Funktion 5. Grades berechnet.

Unabhängig von Deinem Parameterübergabeproblem, dass ja schon beantwortet wurde, würde mich interessieren, wie Du Nullstellen bei einer ganzrationalen Funktion 5.Grades berechnet.
Konkret: Was sagt Deine Prozedur zu y = x^5/8 - x^4/4 - 5/4 x^3 + x^2 + 33/8 x + 9/4
Ich frage, da eine solche Berechnungsroutine bei mehr als 4.Grad nicht trivial ist.

Beste Grüße
Mathematiker

Crattely 29. Apr 2013 19:44

AW: Übergabe von Zahlen an Prozedur
 
Vielen Dank !!!
Da schreibt man die kompliziertesten Programme und dann so ein dummer Fehler :D
NST6 ist eigentlich gar keine Nullstelle, sondern da werden Dinge wie "unendlich viele Nullstellen" oder "keine NSTs", also Sonderfälle reingeschrieben und später ausgewertet.
Die Nullstellen Funktion sieht so aus:

Delphi-Quellcode:
//Beginn Prozedur Funktion
function fktn(a,b,c,d,e,f,x:real):real;

             function pot(x:real;n:integer):real;
             var i:integer;
                 y:real;
             begin
                  y:=1;
                  for i:=1 to n do y:=y*x;
                  pot:=y;
             end;

begin
     fktn:=(a*pot(x,5)+b*pot(x,4)+c*pot(x,3)+d*pot(x,2)+e*x+f);
end;
//Ende Prozedur Funktion

//Beginn Prozedur NS_numerisch
procedure NS_numerisch(a,b,c,d,e,f:real; var NULL_1,NULL_2,NULL_3,NULL_4,NULL_5:real;var i:integer);
var //i:integer;
    x_MIN,x_MAX,x:real;

    function BerechneNullstelle_Numerisch(x_MAX,x_MIN:real):real;
    var Mitte:real;
    begin
         repeat
               Mitte:=(x_MAX + x_MIN)/2;
               if fktn(a,b,c,d,e,f,x_MIN)*fktn(a,b,c,d,e,f,Mitte)>0 then x_MIN := Mitte
               else x_MAX := Mitte;
         until x_MAX - x_MIN < 0.0001;
         BerechneNullstelle_Numerisch := (x_MIN + x_MAX)/2;
    end;

begin
x_MIN := -20;
i := 0; //Gefundene Nullstellenanzahl [Index]

While x_MIN < 20 do begin
      x_MAX := x_MIN + 0.1;
      if fktn(a,b,c,d,e,f,x_MIN)*fktn(a,b,c,d,e,f,x_MAX) < 0 then begin
         x := BerechneNullstelle_Numerisch(x_MAX,x_MIN);
         i:=i+1;
         case i of
              1: NULL_1:= x;
              2: NULL_2:= x;
              3: NULL_3:= x;
              4: NULL_4:= x;
              5: NULL_5:= x;
         end;
      end;
      x_MIN := x_MAX;
end;
end;
//Ende Prozedur NS_numerisch


//Beginn Prozedur Nullstellen allgemein
procedure Nullstellen(a,b,c,d,e,f:real; var NST1,NST2,NST3,NST4,NST5:real; var NST6:string; var Anzahl_NST:integer);
var g:real;
begin
NST6:='0';
If (a=0) and (b=0) and (c=0) then begin
   If d=0 then begin
      If e=0 then begin
             If f=0 then NST6:='x beliebig';
                If f<>0 then NST6:='Keine Nullstellen!';
                end
             else begin
                       Anzahl_NST:=1;
                       NST1:=(-f/e);
             end;
      end
   else begin
     g := (e*e) - (4*d*f);
     If g < 0 then NST6:='Keine Nullstellen!'
     else if g = 0 then begin
                             Anzahl_NST:=1;
                             NST1:=(-e/(2*d))
     end
     else begin
        NST1:=((-e + sqrt(g)) / (2*d));
        Anzahl_NST:=1;
        NST2:=((-e - sqrt(g)) / (2*d));
        Anzahl_NST:=2;
     end;
  end;
end
else begin
Anzahl_NST:=0;
NS_numerisch(a,b,c,d,e,f,NST1,NST2,NST3,NST4,NST5,Anzahl_NST);

end;
end;
//Ende Prozedur Nullstellen allgemein

Relativ kompliziert, komischerweise gibt er, wenn die Nullstelle bei x=0 liegt immer 4,8... als Nullstelle aus
Weiß jemand woran das liegen könnte ? Konnte sich auch mein Lehrer nicht erklären

Mathematiker 29. Apr 2013 20:29

AW: Übergabe von Zahlen an Prozedur
 
Hallo,
Zitat:

Zitat von Crattely (Beitrag 1213452)
Relativ kompliziert, komischerweise gibt er, wenn die Nullstelle bei x=0 liegt immer 4,8... als Nullstelle aus

Gibt er nicht! Für y = x^3 gibt er 4.88281249847122E-5 = -4.8828 10^(-5) aus, d.h. also fast 0. Das hat Dein Lehrer nicht gemerkt?!

Zu Deinem Programm. Genau das habe ich vermutet.
Es funktioniert nämlich nicht. Tut mir leid. Schon für y = x^2 entsteht Merkwürdiges. Er liefert keine(!) Nullstelle.
Immer dann, wenn die Nullstelle nämlich gleichzeitig Extremstelle ist, versagt der von Dir verwendete Algorithmus. Der Test auf Vorzeichenwechsel der Funktion reicht nicht als Kriterium. Vielmehr muss Du auch den der 1.Ableitung entsprechend auswerten. D.h., liegt ein Extremstelle vor, muss getestet werden, ob nicht evtl. auch eine Nullstelle auftritt.
Den Funktionswert würde ich außerdem mit dem Horner-Schema und nicht mit der Potenzbildung bestimmen, da gerade bei Argumenten nahe Null die relativen Fehler sonst zu groß werden.
Weitere Ideen habe ich noch, aber das reicht erst einmal.

Beste Grüße
Mathematiker

Crattely 29. Apr 2013 22:16

AW: Übergabe von Zahlen an Prozedur
 
Hm...vielen Dank für deine Antwort, das mit der Null muss ich also einfach nur richtig formatieren.
Die Berechnung der Werte hatten wir im Unterricht so vorangefertigt, allerdings verpasse ich mich da jetzt mal auf dich und baue stattdessen das Horner Schema ein.
Nur ein Problem habe ich noch:
Ich verstehe den ersten Teil deines Posts ehrlich gesagt nicht so richtig.
Bezieht sich das Problem mit den Nullstellen nur auf das NS_Numerisch Teilprogramm?
Und wo soll ich jetzt genau noch nachbessern ? Das mit dem Vorzeichenwechsel und der ersten Ableitung habe ich irgendwie nicht ganz verstanden :(
Wäre nett wenn du mir das nochmal erklären könntest...
MfG

Mathematiker 29. Apr 2013 22:37

AW: Übergabe von Zahlen an Prozedur
 
Hallo,
Zitat:

Zitat von Crattely (Beitrag 1213461)
Die Berechnung der Werte hatten wir im Unterricht so vorangefertigt, allerdings verpasse ich mich da jetzt mal auf dich und baue stattdessen das Horner Schema ein.

Wenn Ihr das so im Unterricht gemacht habt, dann lasse es auch so. Gibt nur Diskussionen.
Zitat:

Zitat von Crattely (Beitrag 1213461)
Ich verstehe den ersten Teil deines Posts ehrlich gesagt nicht so richtig.

Dein Algorithmus geht schrittweise das Intervall durch und prüft ob das Produkt von zwei benachbarten Funktionswerten negativ ist. Wenn ja und die Funktion ist stetig, liegt eine Nullstelle dazwischen.
Bei Funktionen wie y = x^2, y = x^2+2x+1, y = x^4 und komplizierteren findet dieser Algorithmus die wahrscheinliche Nullstelle nicht. Denn an dieser hat die Funktion eine lokale Extremstelle, d.h. Dein Produkt wird nicht negativ. Damit findest Du nicht alle Nullstellen.
Genau das hatte ich vermutet. Die Berechnung der Nullstellen einer Funktion mit dem Computer(!) ist nämlich nicht so einfach.
Wie kann das geändert werden? Zusätzlich musst Du auch für die 1.Ableitung dieses Testprodukt bilden. Wird es negativ kann eine Extremstelle vorliegen, die vielleicht auch Nullstelle ist.
Deshalb testet man dort mit einem schnellen Verfahren, z.B. Regula falsi, etwa 10 Iterationsschritte. Nähert sich der Funktionswert der Null (z.B. Test |x1-x2|<0.00001) hast Du die Nullstelle ermittelt, die Dir sonst fehlt.

Beste Grüße
Mathematiker

Luckie 29. Apr 2013 22:57

AW: Übergabe von Zahlen an Prozedur
 
Und das:
Delphi-Quellcode:
function fktn(a,b,c,d,e,f,x:real):real;

             function pot(x:real;n:integer):real;
             var i:integer;
                 y:real;
             begin
                  y:=1;
                  for i:=1 to n do y:=y*x;
                  pot:=y;
             end;

begin
     fktn:=(a*pot(x,5)+b*pot(x,4)+c*pot(x,3)+d*pot(x,2)+e*x+f);
end;
Ist auch ein etwas überholtes Konstrukt aus Pascal Zeiten,. In Delphi werden Rückgabewerte mit result zurückgegeben.

Caps 30. Apr 2013 09:27

AW: Übergabe von Zahlen an Prozedur
 
Ich glaube es gibt noch ein Problem:

Angenommen die Schleife, die die Produkte "benachbarter" Funktionswerte auf <0 testet, läuft in die Bedingung f(x_MAX) = 0, d.h. die Intervallgrenze ist selbst eine Nullstelle der Funktion (kann ja vorkommen). Dann wird im nächsten Schritt x_MIN := x_MAX gesetzt. Wenn die Nullstelle jetzt gleichzeitig ein Maximum ist, dann wird das Testprodukt wieder negativ, und die gleiche (die selbe) Nullstelle wird noch einmal gefunden. Der Iterator i ist jetzt aber um 1 größer, d.h. Du füllst die nächste Ergebnisvariable NULL_<i> mit der selben Nullstelle. Dann brauchst Du aber wenigstens 10 solche Ergebnisvariablen, also NULL_1 bis NULL_10, sonst findest Du nicht alle Nullstellen.
Natürlich ist das ein Spezialfall, aber naja... :cheers:.

lg Caps


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:50 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