![]() |
Vergleich von Zahlen
Hallo zusammen,
ich versuche aktuell ein Programm zu machen welches mir Daten konvertiert. Die Daten liegen als Textdateien in einem speziellen Format vor. Das Einlesen und extrahieren der Daten ist soweit kein Problem. Nun habe ich Positionen in einem Stringarray vorliegen. Diese Daten sind in dem Format "0.000000" also mit 6 Nachkommastellen und einem Dezimalpunkt anstelle des Komma. Die Anzahl der Positionen und deren Wert ist prinzipiell frei. Können theoretisch auch Nachkommastellen enthalten z.B. so (die einzelnen Werte habe ich aktuell in einem Stringarray) Zitat:
Diese Version wäre nutzbar. Zitat:
Bin für alle Ideen und Anregungen dankbar. MfG Jürgen |
AW: Vergleich von Zahlen
Ganz banal vielleicht:
Handhabe das wie eine Doppelwoche. Hole dir Wert 1 und 2, vergleiche sie. Sind dort größere, ungewollte Lücken => füllen. Danach Wert 2 und 3, 3 und 4, 4 und 5 usw. |
AW: Vergleich von Zahlen
was ist denn bei
0.000000 100.000000 300.000000 600.000000 1200.000000 falsch? Eine völlig banale Frage: wie kann ich denn ein neues Thema aufmachen? Ich finde es einfach nicht ... bin wahrscheinlich zu blöd |
AW: Vergleich von Zahlen
Eine schlechte Erläuterung von mir.
Es handelt sich um Positionen an denen ein Winkel gemessen wurde. Und ich kann nur meine Berechnungen machen, wenn die Abstände dieser Positionen gleich sind. z.B. alle 100mm Es geht auch nicht darum diese Positionen zu ergänzen. Sondern einfach nur einen Meldung auszugeben das bei nicht regelmäßigen Positionen eine Umrechnung nicht möglich ist. |
AW: Vergleich von Zahlen
wäre es dann nicht einfacher, nur die erste Position sowie den Abstand einzulesen?
|
AW: Vergleich von Zahlen
Zitat:
Vielleicht so? Wenn die Nachkommastellen eh immer 0 sind, kann man das mit Integer machen. Wie man das jetzt mit den Nachkommastellen hinbekommt, weiß ich nicht. Aber es kommt aufs Prinzip an. Das geht bestimmt viel einfacher.
Delphi-Quellcode:
var
i: Integer; Werte, WerteNeu: TArray<Double>; begin try SetLength(Werte, 5); Werte[0] := 0.000000; Werte[1] := 100.000000; Werte[2] := 300.000000; Werte[3] := 600.000000; Werte[4] := 1200.000000; for i := Round(Werte[Low(Werte)]) to Round(Werte[High(Werte)]) do begin SetLength(WerteNeu, Length(WerteNeu) + 1); if i mod 100 = 0 then begin WerteNeu[High(WerteNeu)] := i; WriteLn(i.ToString); end; end; ReadLn; except on E: Exception do WriteLn(E.ClassName, ': ', E.Message); end; end;
Code:
0
100 200 300 400 500 600 700 800 900 1000 1100 1200 |
AW: Vergleich von Zahlen
Ich will kein Array füllen.
Sondern nur prüfen ob die Positionen regelmäßig sind. so in der Art:
Code:
i:= array[1]-array[0];
for j := 2 to length(array)-1 do begin if array[j]-array[j-1] <> i then error := TRUE; end; next; end; if error = TRUE then break; [...]Berechnungen |
AW: Vergleich von Zahlen
Zitat:
Delphi-Quellcode:
if error = TRUE then
|
AW: Vergleich von Zahlen
Das war QD
Außerdem bin ihc jemand der nur ab und zu aus Spaß sowas macht und dann immer offen ist, wenn er ERklärt bekommt was er falsch macht oder was man ordentlicher "sauberer" lösen kann. Aber ich vermute das du auf
Code:
anspielst? Da so eh der Vergleich auf TRUE gemacht wird?
IF error then
So grob funktioniert das jetzt sogar. Allerdings scheint meine Funktion, die mit den String mit Dezimalpunkt in ein Float umwandelt (hier im Forum gefunden) die Nachkommastellen abzuschneiden. Oder Ich runde irgendwo wo ich es im Moment nicht sehe. Habe ich "glatte" Zahlen (ohne Nachkommastelle) bekomme ich das passende Ergebnis. Habe ich, als Beispiel Nachkomma stellen (Der Intervall ist immer 100,1, also wäre es richtig) dann bekomme ich gesagt das mein Ergenis -1 (also ungültig) ist Zitat:
MyStrToFloat() hier im Forum gefunden.
Code:
Meine eigene Funktion:
function MyStrToFloat(AString: string): double;
begin AString := StringReplace(AString, '.', DecimalSeparator, [rfIgnoreCase, rfReplaceAll]); AString := StringReplace(AString, ',', DecimalSeparator, [rfIgnoreCase, rfReplaceAll]); result := StrToFloat(AString); end; In Targets übergebe ich das Stringarray mit den einzelnen Werten. Rückgeliefert werden soll der Intervall in Values.TargetCount ist die Anzahl der vorhandenen Targets.
Code:
function CalculateStep(Targets: array of string): double;
//Größe der Schrittweite, -1 wenn ungueltig var i, j: integer; m, r: double; l: boolean; begin i := 0; j := 0; r := 0; l := False; i := Values.TargetCount; m := MyStrToFloat(Targets[1]) - MyStrToFloat(Targets[0]); for j := 1 to i - 1 do begin if MyStrToFloat(Targets[j]) - MyStrToFloat(Targets[j - 1]) = m then l := True else l := False; end; if l then r := m else r := -1; Form1.Edit1.Text := FloatToStr(m); Form1.Edit2.Text := FloatToStr(r); Form1.Memo1.Text := ArrayToStr(Targets); end; |
AW: Vergleich von Zahlen
Zitat:
Boolean ist 1 Byte groß und kennt somit 256 verschiedene Werte. Die Konstanten True und False sind jeweils als ein Wert definiert (0 oder 1 und z.B. im C++ auch gern als -1 statt 1) 1 = ein Bit aktiv -1 = alle Bits aktiv Die Auswertung eines BOOLs sieht aber anders aus ist 0 = False nicht 0 = True Tja, und nun kann es vorkommen, dass du von irgendwo ein "anderes" True bekommst und somit dein =True nicht mehr trifft.
Delphi-Quellcode:
var
B: Boolean; begin //B := False; //B := True; B := Boolean(2); if B then ShowMessage('1: True'); if not B then ShowMessage('1: False'); if B = True then ShowMessage('2: True'); if B = False then ShowMessage('2: False'); if B <> False then ShowMessage('3: True'); Zitat:
z.B. 123.456,78 Dann knallt es. StrToFloat hat einen Parameter FormatSettings, den sollte man verwenden, wenn man ein bestimmtes Format haben möchte, welches nicht unbedingt der aktuellen Systemsprache entspricht. Zitat:
Delphi-Quellcode:
for j := 1 to i - 1 do
begin l := MyStrToFloat(Targets[j]) - MyStrToFloat(Targets[j - 1]) = m; end;
Delphi-Quellcode:
if i > 2 then // if i - 1 > 1 then
l := MyStrToFloat(Targets[i - 1]) - MyStrToFloat(Targets[i - 2]) = m; Genau, alle nachfolgenden Durchläufe überschreiben diese Variable und somit wird nur das Letzte ausgewertet. Bei z.B. 0.000000 100.000000 123456789.012 -666 300.000000 400.000000 also 0.000000 100.000000 ... irgendwas ... 300.000000 400.000000 (2 vorn und 2 hinten gleich weit entfernt) schlägt deine Prüfschleife fehl. Ich vermute das
Delphi-Quellcode:
ist so nicht gewollt und wenn es dann eh schon TRUE ist, dann kann es nicht noch TRUEr werden, also könnte man beim ersten True die Schleife abbrechen (Break).
else l := False;
Da Fließkommazahlen Rundungafehler enthalten können, aufgrund der binären Speicherung von dezimalen Zahlen und der gegrenzten Anzahl von Bits, Vergleiche immer nur mit IsZero, ![]() |
AW: Vergleich von Zahlen
So?
Delphi-Quellcode:
Nur nebenbei:
type
TValues=Array of Double; FUNCTION CheckRegularity(Values:TValues):Boolean; var I:Integer; Delta:Double; begin Result:=True; if Length(Values)>2 then begin Delta:=Values[1]-Values[0]; for I:=1 to Length(Values)-2 do if not SameValue(Values[I+1]-Values[I],Delta) then begin Result:=False; Exit; end; end; end; In #1 schreibst du Zitat:
Haben die Daten 6 Nachkommastellen oder können sie auch Nachkommastellen enthalten. |
AW: Vergleich von Zahlen
Wow. Viel Input...
Danke euch dafür. Zitat:
Zitat:
Zitat:
Hatte ich aus den Augen verloren und muss ich mich nochmals mit beschäftigen. Zitat:
Wenn der Vergleich das erstemal UNWAHR ist muss ich abbrechen weil dann ja eigentlich die Bedingung, alle Werte im gleichen Intervall, bereits UNWAHR ist und ich auch gar nicht mehr weiter prüfen brauch. Zitat:
Ich versuche es konkreter: Das Format mit den 6 Nachkommastellen steht so fest. Die Werte werden meistens aber nur ganzzahlig sein. Also mit 6x 0 hinter dem Dezimalpunkt. Beispiel: 100.000000 Es könnte aber auch sein das ich keine ganzzahligen Werte habe. Als Beispiel 100,5 was dann als 100.500000 in den Daten dargestellt wird. Daher muss ich wohl mit Fließkommazahlen arbeiten. |
AW: Vergleich von Zahlen
Hab eine andere Funktion im Lazarus Forum gefunden, welche sicherer funktioniert.
Allerdings müsste, um vollständig zu sein, noch 2 Varianten (DezTrenner ',' TausenderTrenner '.' und umgekehrt) zusätzlich behandelt werden.
Code:
Meine CalculateStep() habe ich auch nochmals überarbeitet.
function MyStrToFloat(AString: string): double;
var x: Double; fs: TFormatSettings; begin x := NaN; fs := FormatSettings; fs.DecimalSeparator := ','; fs.ThousandSeparator := ','; if not TryStrToFloat(AString, x, fs) then begin fs := FormatSettings; fs.DecimalSeparator := '.'; fs.ThousandSeparator := '.'; if not TryStrToFloat(AString, x, fs) then x := NaN; end; if IsNaN(x) then Result := 0 else Result := x; end; Soweit ich das bis jetzt getestet habe, funktioniert das alles auch wie gewünscht. Es ergibt sihc für mich allerdings noch eine Frage: Wenn ich den Wert von i prüfe (mehr als 2 Werte, genau 2 Werte, wseniger als 2 Werte) Prüft man mit einzelnen IF Statements und bricht die Funktion ab oder schachtelt man die IFs besser? Oder würde man evtl sogar auf CASE ausweichen? Außerdem nutze ich eine Extra variable um einen Zwischenwert zu berechnen (Variable n) Da ich es so übersichtlicher finde. Oder wäre es besser die Berechnung direkt in der Funktion sameValue() anzugeben?
Code:
Allen ein Danke die sich die Mühe machen und gemacht haben etwas Licht in mein Programmierdunkel zu bringen.
function CalculateStep(Targets: array of string): double;
//Größe der Schrittweite, NaN wenn ungueltig ( wird dann mit IsNaN() geprüft ) var i, j: integer; m, n: double; begin i := Values.TargetCount; // Anzahl der Targets aus dem File m := MyStrToFloat(Targets[1]) - MyStrToFloat(Targets[0]); // 1. Step if i < 2 then begin // Sollte nur ein Wert vorhanden sein, Result := NaN; // liefert die Funktion ungültig zurück exit; end; if i < 3 then // Wenn es weniger als 3 Werte gibt begin // Dann ist der Intervall in Ordnung Result := m; // Es wird der 1.Step zurückgeliefert exit; end; for j := 2 to i - 1 do // 3 Werte oder mehr, prüfen auf gültigen Intervall begin n := MyStrToFloat(Targets[j]) - MyStrToFloat(Targets[j - 1]); if not sameValue(n, m, 0) then begin m := NaN; // Wenn ein Intervall ungültig ist, Abbrechen und break; // Ungültig zurückliefern end; end; Result := m; // Alle Intervall OK, also Wert zurückgeben end; |
AW: Vergleich von Zahlen
Zitat:
Da sich sowas nicht ändert und man das öfters gebraucht...
Delphi-Quellcode:
Dann fliegt erstmal die ständige Definition raus
// global bzw. zentral
var FSUS, FSDE: TFormatSettings; // Init { FSUS := FormatSettings; FSUS.DecimalSeparator := '.'; FSUS.ThousandSeparator := ','; FSDE := FormatSettings; FSDE.DecimalSeparator := ','; FSDE.ThousandSeparator := '.'; } FSUS := TFormatSettings.Create('en-US'); // oder TFormatSettings.Create($0409); FSDE := TFormatSettings.Create('de-DE'); // oder TFormatSettings.Create($0407);
Delphi-Quellcode:
und wenn man weiter Unnötiges entfernt, dann bleibt nicht mehr viel übrig
function MyStrToFloat(const AString: string): double;
var x: Double; begin x := NaN; if not TryStrToFloat(AString, x, FSUS) then begin if not TryStrToFloat(AString, x, FSDE) then x := NaN; end; if IsNaN(x) then Result := 0 else Result := x; end;
Delphi-Quellcode:
oder
function MyStrToFloat(const AString: string): double;
begin if not TryStrToFloat(AString, Result, FSUS) and not TryStrToFloat(AString, Result, FSDE) then Result := 0; end;
Delphi-Quellcode:
function MyStrToFloat(const AString: string): double;
begin if not TryStrToFloat(AString, Result, FSUS) then Result := StrToFloatDef(AString, 0, FSDE); end; |
AW: Vergleich von Zahlen
Interessant wie weit man das verkürzen kann.
Danke für die Tipps |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:10 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-2025 by Thomas Breitkreuz