Math unit
Math unit
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
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
-
- 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
Code: Alles auswählen
uses
Math;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Math unit
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
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
Re: Math unit
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.
[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.
-
- 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
Was ist WW2 und RAB ? Welche Werte habe diese bei der Übergabe ?
Durch drücken von Ctrl+F2 in der IDE kannst du dein Programm auch nicht unterbrechen ?Komme dann nur noch mit Str-Alt-Entf wieder raus.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- 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
Folgender Test, gibt keinen Absturz, es kommt nur "Nan";Also dürfte der ArcSin nur auch zwischen -1 und 1 definiert sein.
Code: Alles auswählen
ShowMessage(FloatToStr(arcsin(12)));
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
Mit Java und C/C++ sehe ich rot
Re: Math unit
+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".
[EDIT]
Achja, und "NaN" heißt "Not a Number" = "keine Zahl".
Re: Math unit
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
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
Re: Math unit
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.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.
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.
Re: Math unit
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
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
Re: Math unit
Hallo,
meine Berechnungen funktionieren, dank Eurer Unterstützung, nun soweit:
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
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;
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
-
- 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
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;
.
Re: Math unit
Danke!
Schon eingebaut. Funktioniert bestens.
Schon eingebaut. Funktioniert bestens.