Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   double in Schleife und Nachkommastellen (https://www.delphipraxis.net/216309-double-schleife-und-nachkommastellen.html)

ebi 7. Dez 2024 17:24

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;

jaenicke 7. Dez 2024 19:12

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.

Redeemer 9. Dez 2024 13:22

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.

MyRealName 9. Dez 2024 13:52

AW: double in Schleife und Nachkommastellen
 
Wir haben das immer mit der Funktion SameValue gelöst :

Code:
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;
Als 3. Parameter hat man noch den Epsilon Wert, wo Du sozusagen die Toleranz einstellen kannst

Code:
function SameValue(A, B: Double; Epsilon: Double = 1E-12): Boolean;
Sorry, Du willst ja nicht auf den gleichen Wert vergleichen, sondern ob etwas grösser ist, dazu nimmt man CompareValue


Code:
function CompareValue(const A, B: Extended; Epsilon: Extended): TValueRelationship;
TValueRelationship gibt dir dann zurück, ob es Grösser, kleiner oder gleich ist...

Dennis07 11. Dez 2024 15:02

AW: double in Schleife und Nachkommastellen
 
Anmerken will ich hier noch die Funktion
Delphi-Quellcode:
IsZero(...)
, die im Grunde die selbe Funktion wie
Delphi-Quellcode:
SameValue(..., 0)
erfüllt, nur dass sie auf das zero-flag prüft.

Alter Mann 11. Dez 2024 19:40

AW: double in Schleife und Nachkommastellen
 
Für eine Test-Prog habe ich das genutzt:
Code:
...
  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;
...
und zurück

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