![]() |
double in Schleife und Nachkommastellen
Liste der Anhänge anzeigen (Anzahl: 1)
hallo Zusammen,
weshalb kommen plötzlich so viele Nachkomma Zahlen?
Delphi-Quellcode:
procedure TFormStechen.berechnen();
var P1, P2, P5, P6: TKoordinate; P: TMittelpunkt; aussenDm, grundDm, process, ap, safety, returnX: double; X_inc: double; drehrichtung: string; Zaehler: integer; begin Zaehler := 1; X_inc := 0; abbruch := false; try try aussenDm := StrToFloat(EditAussendurchmesser.Text); process := StrToFloat(Edit_process.Text); ap := StrToFloat(EditZustellung.Text); safety := StrToFloat(EditSicherheitsabstand.Text); returnX := StrToFloat(EditSicherheitsposition.Text); drehrichtung := ComboBoxDrehrichtung.Text; grundDm := FGrundDm; P1.X := aussenDm; P1.Z := FStartPkt; P2.X := FRadiusDm; P2.Z := FStartPkt; P5.X := FRadiusDm; P5.Z := FEndPkt; P6.X := aussenDm; P6.Z := FEndPkt; X_pos := P1.X; Z_pos := P1.Z; if (FormMain.RichEditMain.Lines.Count <> 0) then NC_program(Format('M%d'#13#10, [1])); NC_program(Format('(Stechdrehen: %s)', [FormatDateTime('yy-mm-dd hh:nn:ss am/pm', Now())])); NC_program(Format('G0 X%g', [returnX])); NC_program(Format('G0 Z%g', [Z_pos])); NC_program(Format('G0 X%g', [X_pos + safety])); if (Z_pos = P2.Z) then Z_pos := P5.Z else Z_pos := P2.Z; NC_program(Format('G1 X%g', [X_pos])); NC_program(Format('G1 Z%g', [Z_pos])); FormMain.SubProcessBar(FormMain.ProgressBarMain, true, Floor(FEinstichtiefe / ap)); repeat X_pos := X_pos - ap; if (X_pos < P2.X) then X_pos := P2.X; if (Z_pos = P2.Z) then Z_pos := P5.Z else Z_pos := P2.Z; NC_program(Format('G1 X%g', [X_pos])); NC_program(Format('G1 Z%g', [Z_pos])); if ((Zaehler * ap) > process) then begin Zaehler := 1; abfahren(safety); NC_program(Format('G0 X%g', [returnX])); NC_program(Format('M%d', [1])); anfahren(safety); end else Zaehler := Zaehler + 1; if (abbruch) then exit; FormMain.Prozess(); until not(RoundTo(X_pos, -3) > RoundTo(P2.X, -3)); P.mpX := X_pos; repeat P.mpX := P.mpX - ap; X_inc := X_inc + ap; if (P.mpX < grundDm) then begin P.mpX := grundDm; X_inc := X_pos - grundDm; end; if (Z_pos = P2.Z) then begin P.mpZ := Z_pos - X_inc / 2; P.mpI := 0; P.mpK := (X_inc / 2) * (-1); NC_program(Format('G2 X%g Z%g I%g K%g', [P.mpX, P.mpZ, P.mpI, P.mpK])); P.mpZ := P5.Z + (X_inc / 2); NC_program(Format('G1 Z%g', [P.mpZ])); P.mpZ := P5.Z; P.mpI := X_inc / 2; P.mpK := 0; NC_program(Format('G2 X%g Z%g I%g K%g', [X_pos, P.mpZ, P.mpI, P.mpK])); Z_pos := P5.Z; end else begin P.mpZ := Z_pos + X_inc / 2; P.mpI := 0; P.mpK := X_inc / 2; NC_program(Format('G3 X%g Z%g I%g K%g', [P.mpX, P.mpZ, P.mpI, P.mpK])); P.mpZ := P2.Z - (X_inc / 2); NC_program(Format('G1 Z%g', [P.mpZ])); P.mpZ := P2.Z; P.mpI := X_inc / 2; P.mpK := 0; NC_program(Format('G3 X%g Z%g I%g K%g', [X_pos, P.mpZ, P.mpI, P.mpK])); Z_pos := P2.Z; end; if (abbruch) then exit; FormMain.Prozess(); until not(RoundTo(P.mpX, -3) > RoundTo(grundDm, -3)); abfahren(safety); NC_program(Format('G0 X%g', [returnX])); except on e: EConvertError do ShowMessage(e.Message); end; finally FormMain.SubProcessBar(FormMain.ProgressBarMain, false, 0); abbruch := true; end; end; |
AW: double in Schleife und Nachkommastellen
Das liegt an der internen Binärdarstellung, das ist schon korrekt so. Wenn du eine bestimmte Anzahl Nachkommastellen möchtest, musst du das entsprechend formatiert ausgeben, z.B. mit dem Format %.2f.
|
AW: double in Schleife und Nachkommastellen
Ein Computer kann wenige Gleitkommazahlen speichern und mit denen korrekt rechnen. Unter anderem müssen alle Gleitkommazahlen auf 5 enden, aber selbst von denen gehen die meisten nicht. 0,25+0,5 kann ein Computer beispielsweise berechnen, 0,15+0,5 hingegen nicht.
Alternative ist Currency. Das ist ein Int64, das implizit als Zehntausendstel behandelt wird. Du kannst also Zahlen mit vier Nachkommastellen exakt darin speichern und berechnen. Dafür musst du aber wissen, dass du niemals mit mehr als vier Nachkommastellen arbeiten musst. |
AW: double in Schleife und Nachkommastellen
Wir haben das immer mit der Funktion SameValue gelöst :
Code:
Als 3. Parameter hat man noch den Epsilon Wert, wo Du sozusagen die Toleranz einstellen kannst
uses
Math; var Value1, Value2: Double; begin Value1 := 3.14159265358979; Value2 := 3.14159265358978; if SameValue(Value1, Value2) then ShowMessage('Die Werte sind gleich.') else ShowMessage('Die Werte sind unterschiedlich.'); end;
Code:
Sorry, Du willst ja nicht auf den gleichen Wert vergleichen, sondern ob etwas grösser ist, dazu nimmt man CompareValue
function SameValue(A, B: Double; Epsilon: Double = 1E-12): Boolean;
Code:
TValueRelationship gibt dir dann zurück, ob es Grösser, kleiner oder gleich ist...
function CompareValue(const A, B: Extended; Epsilon: Extended): TValueRelationship;
|
AW: double in Schleife und Nachkommastellen
Anmerken will ich hier noch die Funktion
Delphi-Quellcode:
, die im Grunde die selbe Funktion wie
IsZero(...)
Delphi-Quellcode:
erfüllt, nur dass sie auf das zero-flag prüft.
SameValue(..., 0)
|
AW: double in Schleife und Nachkommastellen
Für eine Test-Prog habe ich das genutzt:
Code:
und zurück
...
procedure cnc_Rectangle(XMi, YMi, XMa, YMa: Single; Z : Integer; F : TFormatSettings); var X1, X2, Y1, Y2 : Integer; begin Memo1.Lines.Add('G1 X' + FormatFloat('0.000',XMi, F) + ' Y' + FormatFloat('0.000',YMi, F)); Memo1.Lines.Add('G1 X' + FormatFloat('0.000',XMa, F) + ' Y' + FormatFloat('0.000',YMi, F)); Memo1.Lines.Add('G1 X' + FormatFloat('0.000',XMa, F) + ' Y' + FormatFloat('0.000',YMa, F)); Memo1.Lines.Add('G1 X' + FormatFloat('0.000',XMi, F) + ' Y' + FormatFloat('0.000',YMa, F)); Memo1.Lines.Add('G1 X' + FormatFloat('0.000',XMi, F) + ' Y' + FormatFloat('0.000',YMi, F)); X1 := Round((XMi * PpMM) * Z); Y1 := Round((YMi * PpMM) * Z); X2 := Round((XMa * PpMM) * Z); Y2 := Round((YMa * PpMM) * Z); Image1.Picture.Bitmap.Canvas.Rectangle(X1, Y1, X2, Y2); end; ...
Code:
function StrToFloatEx(const S: string; const AFormatSettings: TFormatSettings): Extended;
var S1, S2 : string; IsNegativ : Boolean; Ret : Extended; begin IsNegativ := S[1] = '-'; S1 := Copy(S, 1, Pos(AFormatSettings.DecimalSeparator, S) -1); S2 := '0,' + Copy(S, Pos(AFormatSettings.DecimalSeparator, S) + 1, Length(S)); Ret := StrToInt(S1) + StrToFloat(S2); if IsNegativ then Result := Ret * -1 else Result := Ret; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:13 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz