Math unit

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Math unit

Beitrag von Johannes »

Hallo Experten,

kaum habe ich meine Vorstellung geschrieben kommt schon eine Frage. Hoffentlich blamiere ich mich nicht gleich beim ersten Post.

Mein kleines Projekt , "Die Heusinger-Steuerung am Modell", lernt langsam das Laufen.
Jetzt sollen die ersten Berechnungen erfolgen. Dazu habe ich Formeln wie,z.B.: ZW4:= ArcSin(ZW2/RAB)*57.29578
Leider bekomme ich hier Fehlermeldungen weil Lazarus "ArcSin" usw. nicht kennt. Meine Suche ergab, dass ich zur lösung des Problems eine Math unit einbinden soll.
Wo kann ich diese finden und einbinden? Onboard ist scheinbar nix dabei.
Ich benutze: 1.6RC1

MfG

Hannes

Mathias
Beiträge: 6918
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Math unit

Beitrag von Mathias »

Code: Alles auswählen

uses
  Math;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: Math unit

Beitrag von Johannes »

Hallo Mathias,

Danke, aber wenn ich das mache bleibt meine Anwendung beim Zugriff auf die Formel stehen.
Komme dann nur noch mit Str-Alt-Entf wieder raus.
Beim Übersetzen bekomme ich keine Fehlermeldungen.

Hier nochmals die Formel: ZW4:= ArcSin(ZW2/RAB)*57.29578

Hannes

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: Math unit

Beitrag von wp_xyz »

Wenn ich mich richtig an meine Schulzeit erinnere, liegt der Wertebereich des Sin zwischen -1 und 1. Also dürfte der ArcSin nur auch zwischen -1 und 1 definiert sein. Also darf ZW2/RAB nicht kleiner als -1 bzw. größer als 1 sein, sonst kann der ArcSin nicht berechnet werden. Außerdem darf RAB nicht null sein (Division durch 0). Warum dein Program damit keine ordentliche Fehlermeldung bringt, weiß ich nicht, dazu müsstest du schon etwas mehr zeigen.

[EDIT] Ich sollte noch erwähnen, dass du dich auf dem gefährlichen Gebiet der Gleitkomma-Arithmetik bewegst, die auf dem Computer keineswegs trivial ist. Selbst wenn dir der Debugger anzeigen sollte, dass ZW2 und RAB gleich groß sind, könnte sein dass wegen Rundungsfehlern der Quotient ZW2/RAB minimal größer ist als 1, etwa 1.00000000000000084 - und schon schmiert der ArcSin ab. Konkret heißt das, dass du solche Sonderfälle immer prüfen musst.

Code: Alles auswählen

const
  EPS = 1E-8;
...
  if RAB = 0.0 then
    // ... Kontrollierte Fehlermeldung anzeigen
  else
  if SameValue(ZW2, RAB, EPS) then 
    ZW4 := 90.0 
  else if SameValue(ZW2, -RAB, EPS) then 
    ZW3 := -90
  else ZW3 := RadToDeg(arcsin(ZW2/RAB));  
Zuletzt geändert von wp_xyz am Mi 20. Jan 2016, 18:32, insgesamt 1-mal geändert.

Mathias
Beiträge: 6918
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Math unit

Beitrag von Mathias »

Was ist WW2 und RAB ? Welche Werte habe diese bei der Übergabe ?
Komme dann nur noch mit Str-Alt-Entf wieder raus.
Durch drücken von Ctrl+F2 in der IDE kannst du dein Programm auch nicht unterbrechen ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6918
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Math unit

Beitrag von Mathias »

Also dürfte der ArcSin nur auch zwischen -1 und 1 definiert sein.
Folgender Test, gibt keinen Absturz, es kommt nur "Nan";

Code: Alles auswählen

ShowMessage(FloatToStr(arcsin(12)));    
Auch 10/0 gibt keinen Absturz, es kommt "+Inf", was das auch immer heisst.

Ich denke mal, es wurde eine Endlosschleife eingebaut, wie schon gesagt man müsste mehr Code sehen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: Math unit

Beitrag von wp_xyz »

+Inf heißt "Infinite" = unendlich, die "größte" Gleitkommazahl (auch wenn Mathematiker bei dieser Aussage mit den Augen rollen...).

[EDIT]
Achja, und "NaN" heißt "Not a Number" = "keine Zahl".

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: Math unit

Beitrag von Johannes »

Hallo,

ich denke, dass ich mit Eurer Hilfe nun das Problem erkannt habe.
Zum Zeitpunkt der Berechnung (ZW4:= ArcSin(ZW2 / RAB)*57.29578; ) ist ZW2 = -0.093 und RAB = 4.85................. .
RAB hat nach Berechnung aus einer anderen Routine (sehr) viele Nachkommastellen. Wenn ich RAB den Wert 4.85 zuweise klappert Alles so wie es soll.
Nun muss ich schauen wie ich auf 2 Stellen hinter dem separator komme.

Herzlichen Dank für die schnelle Unterstützung!

Hannes

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: Math unit

Beitrag von wp_xyz »

Johannes hat geschrieben:Zum Zeitpunkt der Berechnung (ZW4:= ArcSin(ZW2 / RAB)*57.29578; ) ist ZW2 = -0.093 und RAB = 4.85................. .
RAB hat nach Berechnung aus einer anderen Routine (sehr) viele Nachkommastellen. Wenn ich RAB den Wert 4.85 zuweise klappert Alles so wie es soll.
Nun muss ich schauen wie ich auf 2 Stellen hinter dem separator komme.
Diese Werte sind so in Ordnung, der Quotient ZW2/RAB ist betragsmäßig kleiner als 1. Auch dass RAB sehr viele Nachkommastellen hat, ist normal. Fange auf keinen Fall an, während der Rechnung irgendetwas zu runden. Mit jedem Rundungsvorgang wird das Ergebnis ungenauer. Wenn dich die vielen Nachkommastellen stören, dann ändere das erst in der Ausgabe des Endergebnisses.

Du hast oben den tatsächlichen Wert von RAB nicht ausgeschrieben. Steht da am Ende vielleicht etwas mit "E-"? Angenommen, es würde dir RAB = 4.8593234243234E-3 angezeigt, dann wäre die "schön" geschriebene Zahl 0.004.8593234243234 - und wenn du ZW2 dadurch dividierst, wäre das Verhältnis tatsächlich kleiner als -1. Ich hoffe, du kennst die Exponentialdarstellung von Zahlen.

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: Math unit

Beitrag von Johannes »

Hallo,

vielen Dank!
Über meinen letzten Beitrag ärgere ich mich sehr.
Der Fehler war ganz einfach der, dass die Variable "RAB" zum Zeitpunkt der Berechnung noch keinen Wert hatte!
Selbstverständlich runde ich nur die Ausgaben (Label usw.).

Nochmals Danke

Hannes

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: Math unit

Beitrag von Johannes »

Hallo,

meine Berechnungen funktionieren, dank Eurer Unterstützung, nun soweit:

Code: Alles auswählen

procedure TMathe.Button1Click(Sender: TObject);
begin
 
                // ZW1 Schiebermittellinie zum Schwingenlager (vert.)
   ZW1:= sqrt((EingabeA.IAF**2-(EingabeI.IIG+EingabeI.IIH)**2));
   EdZW1.Text:=FloatToStrF(ZW1,ffNumber,10,3);
                // ZW2
   ZW2:= ((EingabeA.IAD)-ZW1-(EingabeA.IAC));
   EdZW2.Text:=FloatToStrF(ZW2,ffNumber,10,3);
                // ZW3
   ZW3:=  EingabeA.IAA-(EingabeA.IAB+ EingabeA.IAE);
   EdZW3.Text:=FloatToStrF(ZW3,ffNumber,10,3);
                //Schwingenstange
   RAB:= sqrt((ZW2*ZW2)+(ZW3*ZW3));
   EdRAB.Text:= FloatToStrF(RAB,ffNumber,10,3);
                // ZW4 gamma
   ZW4:=(ARCSIN(ZW2/RAB))*57.29578;
   EdZW4.Text:= FloatToStrF(ZW4,ffNumber,10,3);
                // ZW5 halber Schieberweg
   ZW5:=RAA/2;
   EdZW5.Text:=FloatToStrF(ZW5,ffNumber,10,3);
                // ZW6 e + k
   ZW6:= EingabeI.IIG+EingabeI.IIH;
   EdZW6.Text:=FloatToStrF(ZW6,ffNumber,10,3);
                // Lower Pins
   RAD:= ((EingabeI.III/2)*EingabeA.IAF)/ZW6;
   EdRAD.Text:=FloatToStrF(RAD,ffNumber,10,3);
                // Overall Pins
   RAE:=EingabeA.IAF+RAD;
   EdRAE.Text:= FloatToStrF(RAE,ffNumber,10,3);
                 // ZW7 M14
   ZW7:= SQRT(RAE**2-(ZW6+(EingabeI.IIA / 2))**2);
   EdZW7.Text:=FloatToStrF(ZW7,ffNumber,10,3);
                 // ZW8 M15
   ZW8:= (RAE-ZW7)/2;
   EdZW8.Text:=FloatToStrF(ZW8,ffNumber,10,3);
                 // Anchor Link
   RAF:= sqrt(((EingabeA.IAA-(EingabeA.IAE+EingabeA.IAG))**2)+(ZW8**2));
   EdRAF.Text:=  FloatToStrF(RAF,ffNumber,10,3);
                 // Drop Link
   RAG:= RAE-ZW8-EingabeA.IAD;
   EdRAG.Text:=FloatToStrF(RAG,ffNumber,10,3);
                 //ZW9 x Quadratur
   ZW9:= SQRT(ZW5**2-ZW6**2);
   EdZW9.Text:=FloatToStrF(ZW9,ffNumber,10,3);
                 //ZW10 x*y/l
   ZW10:=ZW9*(RAD/RAE);
   EdZW10.Text:=FloatToStrF(ZW10,ffNumber,10,3);
                 //max. Schwingenausschlag
   RAH:= ((ARCSIN(ZW10/EingabeA.IAI))*2)*57.29578;
   EdRAH.Text:=FloatToStrF(RAH,ffNumber,10,3);
                 //ZW11 d
   ZW11:=SQRT(EingabeA.IAB**2+EingabeA.IAC**2);
   EdZW11.Text:=FloatToStrF(ZW11,ffNumber,10,3);
                 //ZW12 dc
   ZW12:= ZW11*EingabeA.IAH;
   EdZW12.Text:=FloatToStrF(ZW12,ffNumber,10,3);
                 //ZW13 d^2+c^2
   ZW13:= ZW11**2+EingabeA.IAH**2;
   EdZW13.Text:=FloatToStrF(ZW13,ffNumber,10,3);
                 //ZW14 cos f
   ZW14:= COS(ZW12/57.29578);
   EdZW14.Text:=FloatToStrF(ZW14,ffNumber,10,3);
                 //ZW15 beta
   ZW15:= ((ARCCOS((ZW12/ZW13)*(1+ZW14))))*57.29578;
   EdZW15.Text:=FloatToStrF(ZW15,ffNumber,10,3);
                 //ZW16 theta
   ZW16:= (57.29578*(ARCTAN(EingabeA.IAB/EingabeA.IAC)))-ZW15;
   EdZW16.Text:=FloatToStrF(ZW16,ffNumber,10,3);
                 //ZW17 1/2 Swing Exp.link(f)
   ZW17:=(ARCSIN(ZW10/EingabeA.IAI))* 57.29578;
   EdZW17.Text:=FloatToStrF(ZW17,ffNumber,10,3);
                 //ZW18 Backset Angel
   ZW18:= ZW16+ZW4;
   EdZW18.Text:=FloatToStrF(ZW18,ffNumber,10,3);
                 //ZW19 sin beta
   ZW19:= SIN(ZW15/57.29578);
   EdZW19.Text:=FloatToStrF(ZW19,ffNumber,10,3);
                 //ZW20 cos beta
   ZW20:= COS(ZW15/57.29578);
   EdZW20.Text:=FloatToStrF(ZW20,ffNumber,10,3);
                 //ZW21 delta
   ZW21:=ARCTAN((EingabeA.IAH*ZW19)/(ZW11-(EingabeA.IAH*ZW20)))*57.29578;
   EdZW21.Text:=FloatToStrF(ZW21,ffNumber,10,3);
                 //ZW22 psi
   ZW22:= 90-(ZW16+ZW15+ZW21);
   EdZW22.Text:=FloatToStrF(ZW22,ffNumber,10,3);
                 //Schieberweg
   RAA:= (EingabeI.IIG+EingabeI.IIH)*2+(EingabeI.IIJ*2);
   EdRAA.Text:= FloatToStr(RAA);
                 // Angel of swing
   RAC  :=((ARCSIN(ZW6/EingabeA.IAF))*2)*57.29578;
   EdRAC.Text:=FloatToStrF(RAC,ffNumber,10,3);
                 // Lower Pins
   RAD:= ((EingabeI.III/2)*EingabeA.IAF)/ZW6; //((D8/2)*D5)/D4
   EdRAD.Text:=FloatToStrF(RAD,ffNumber,10,3);
                 // Backset
   RAI:=EingabeA.IAH*(SIN(0.0174532*(ZW18)));
   EdRAI.Text:=FloatToStrF(RAI,ffNumber,10,3);
                 // Pitch - Gegenkubelkreis
   RAJ:= (ZW11*EingabeA.IAH*(SIN(ZW17/57.29578)))/(SQRT(ZW13));
   EdRAJ.Text:= FloatToStrF(RAJ,ffNumber,10,3);
                 // Eccentric Rod
   RAK:= SIN(ZW15/57.29578)*SQRT(ZW13);
   EdRAK.Text:= FloatToStrF(RAK,ffNumber,10,3);
                 // ZW23  90 - psi
   ZW23:= 90 - ZW22;
   EdZW23.Text:= FloatToStrF(ZW23,ffNumber,10,3);
                 // ZW24  90 + psi
   ZW24:= 90 + ZW22;
   EdZW24.Text:= FloatToStrF(ZW24,ffNumber,10,3);
                 // ZW25  cos chi -
   ZW25:= COS(ZW23/57.29578);
   EdZW25.Text:=  FloatToStrF(ZW25,ffNumber,10,3);
                 // ZW26  cos chi +
   ZW26:= COS(ZW24/57.29578);
   EdZW26.Text:= FloatToStrF(ZW26,ffNumber,10,3);
                 // Return Crank (where Main Crank follows)
   RAL:= SQRT(RAJ**2+(EingabeI.IIA/2)**2-(2*(EingabeI.IIA/2)*RAJ*ZW25));
   EdRAL.Text:= FloatToStrF(RAL,ffNumber,10,3);
                 // Return Crank (where Main Crank leads)
   RAM:= SQRT(RAJ**2+(EingabeI.IIA/2)**2-(2*(EingabeI.IIA/2)*RAJ*ZW26));
   EdRAM.Text:= FloatToStrF(RAM,ffNumber,10,3);
                 // Full Gear Cutt Off %
   RAN:= (1/(2*ZW5**2)*(ZW5**2-EingabeI.IIG**2-(EingabeI.IIG*EingabeI.IIH)+SQRT
   ((ZW5**2-EingabeI.IIG**2)*(ZW5**2-((EingabeI.IIG+EingabeI.IIH)**2)))))*100;
   EdRAN.Text:= FloatToStrF(RAN,ffNumber,10,3);
 
   end;                                                 
Wenn ich das Programmchen nicht aus der IDE starte und eine unerlaubte Rechenoperation ausführen will bekomme ich eine Fehlermeldund "Illegal Float Operation".
Dabei kommt es aber nicht zum Absturz. Ich kann auswählen das Programm weiter auszuführen (ev.Datenverlust) oder abbrechen. Das sieht schon besser aus.
Wie ich eine Überprüfung für jede Rechenoperation einbauen kann ist mir noch nicht klar. Die Formeln werden mit Daten gefüllt die, zum Teil, aus ca. 20 Eingabefeldern stammen.

Mit freundlichen Grüßen

Hannes

baumina
Beiträge: 152
Registriert: Mo 3. Feb 2014, 14:07
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Math unit

Beitrag von baumina »

Fehler abfangen könntest du folgendermaßen machen

Code: Alles auswählen

 
try
  Formelberechnung
except
  on E : Exception do
  begin
    showmessage('Fehler : ' + e.Message);
  end;
end;
 
.

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: Math unit

Beitrag von Johannes »

Danke!
Schon eingebaut. Funktioniert bestens.

Antworten