AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

double in Schleife und Nachkommastellen

Ein Thema von ebi · begonnen am 7. Dez 2024 · letzter Beitrag vom 11. Dez 2024
Antwort Antwort
ebi

Registriert seit: 8. Sep 2024
11 Beiträge
 
Delphi 12 Athens
 
#1

double in Schleife und Nachkommastellen

  Alt 7. Dez 2024, 17:24
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;
Miniaturansicht angehängter Grafiken
screenshot-2024-12-07-171938.png  
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: double in Schleife und Nachkommastellen

  Alt 7. Dez 2024, 19:12
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.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
1.081 Beiträge
 
Delphi 2009 Professional
 
#3

AW: double in Schleife und Nachkommastellen

  Alt 9. Dez 2024, 13:22
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.
Janni
2005 PE, 2009 PA, XE2 PA
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
679 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: double in Schleife und Nachkommastellen

  Alt 9. Dez 2024, 13:52
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...

Geändert von MyRealName ( 9. Dez 2024 um 13:55 Uhr)
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
488 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: double in Schleife und Nachkommastellen

  Alt 11. Dez 2024, 15:02
Anmerken will ich hier noch die Funktion IsZero(...) , die im Grunde die selbe Funktion wie SameValue(..., 0) erfüllt, nur dass sie auf das zero-flag prüft.
Dennis
  Mit Zitat antworten Zitat
Alter Mann

Registriert seit: 15. Nov 2003
Ort: Berlin
947 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: double in Schleife und Nachkommastellen

  Alt 11. Dez 2024, 19:40
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;
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:40 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