AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Seltsames Verhalten einer Funktion

Ein Thema von Pytroxis · begonnen am 24. Apr 2019 · letzter Beitrag vom 28. Apr 2019
Antwort Antwort
Seite 1 von 4  1 23     Letzte » 
Pytroxis

Registriert seit: 12. Apr 2019
46 Beiträge
 
#1

Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 11:34
Delphi-Version: 10.2 Tokyo
Hey,

ich bin es mal wieder, langsam verzweifle ich an Delphi

Bei meinem Programm werden Boxplots dargestellt/gezeichnet, prinzipiell funktioniert das auch.
Nun habe ich mich daran versucht 2 unterschiedliche Boxplots darzustellen und bin auf ein sehr großes Problem gestoßen:
Wenn beide Boxplots den gleichen Datensatz haben werden sie Normal dargestellt, sofern aber einer der Boxplots einen anderen Datensatz besitzt wird der erste nicht mehr korrekt dargestellt (siehe Anhang).
Ich habe bereits einiges getestet und bin zu folgendem Entschluss gekommen:
  • Es liegt nicht an dem sortieren /einlesen. Datensatz wird korrekt abgespeichert bzw. eingelesen und sortiert (-> Mehrfach überprüft).
  • Es muss an der Funktion für das zeichnen liegen
Ich habe die Funktion nun mehrfach neu geschrieben und auf Fehler überprüft aber ich finde einfach keinen (-> Bestimmt ein ganz simpler Fehler, den ich einfach nicht finde).

Dementsprechend hier die Funktion (bitte schlagt mich nicht für den schlechten Stil):
Delphi-Quellcode:
var
  zahlen : array of array of Double;
  namen : TStrings;
  quartils : array[0..1] of Double;
  median : Double;
  bereiche: array[0..3] of array of Double;

...

procedure drawLine(PaintBox:TPaintBox; color: TColor; minX, minY, maxX, maxY:integer);
 begin
  PaintBox.Canvas.Pen.Color := color;
  PaintBox.Canvas.MoveTo(minX, minY);
  PaintBox.Canvas.LineTo(maxX, maxY);
 end;

 procedure zeichnen(PaintBox : TPaintBox; Boxplot : real; FHeight, FWidth: Integer);
  var i, xWert, Height, index: integer;
      eineLaengeneinheit : Double;
      getHeight : array[0..9] of integer;


  begin
    if Length(zahlen) > 0 then begin
      xWert := 40;
      Height := round(FHeight * 0.4);
      index := Round(Boxplot);

      eineLaengeneinheit := (FWidth-120) / round(zahlen[index][Length(zahlen[index])-1] - zahlen[index][0]);


      getHeight[0] := round(FHeight * 0.31919 + Height * Boxplot);
      getHeight[1] := round(FHeight * 0.13214 + Height * Boxplot);
      getHeight[2] := round(FHeight * 0.18379 + Height * Boxplot);
      getHeight[3] := round(FHeight * 0.04839 + Height * Boxplot);
      getHeight[4] := round(FHeight * 0.09839 + Height * Boxplot);
      getHeight[5] := round(FHeight * 0.21839 + Height * Boxplot);
      getHeight[6] := round(FHeight * 0.15839 + Height * Boxplot);
      getHeight[7] := round(FHeight * 0.26839 + Height * Boxplot);
      getHeight[8] := round(FHeight * 0.28839 + Height * Boxplot);
      getHeight[9] := round(FHeight * 0.27839 + Height * Boxplot);

      // Name des Boxplots
      PaintBox.Canvas.TextOut(xWert-30, getHeight[3]-20, namen[index] + ':');

      // Einteilung/Markierung
        // Minimum
      PaintBox.Canvas.TextOut(xWert-3, getHeight[0], FloatToStr(zahlen[index][0]));
      drawLine(PaintBox, clRed, xWert, getHeight[1], xWert, getHeight[2]);

        // Maximum
      PaintBox.Canvas.TextOut(FWidth - 80, getHeight[0], FloatToStr(zahlen[index][Length(zahlen[index]) - 1]));
      drawLine(PaintBox, clRed, FWidth-80, getHeight[1], FWidth-80, getHeight[2]);

        // unteres Quartil
      PaintBox.Canvas.TextOut(round(xWert - 3 + (quartils[0] - zahlen[index][0]) * eineLaengenEinheit), getHeight[3], FloatToStr(quartils[0]));
      drawLine(PaintBox, clRed, round(xWert + (quartils[0] - zahlen[index][0])*eineLaengenEinheit), getHeight[4], round(xWert +
        (quartils[0] - zahlen[index][0])*eineLaengenEinheit), getHeight[5]);

        // median
      PaintBox.Canvas.TextOut(round(xWert - 3 + (median - zahlen[index][0]) * eineLaengenEinheit), getHeight[3], FloatToStr(median));
      drawLine(PaintBox, clRed, round(xWert + (median - zahlen[index][0])*eineLaengenEinheit), getHeight[4], round(xWert +
        (median - zahlen[index][0])*eineLaengenEinheit), getHeight[5]);

        // oberes Quartil
      PaintBox.Canvas.TextOut(round(xWert - 3 + (quartils[1] - zahlen[index][0]) * eineLaengenEinheit), getHeight[3], FloatToStr(quartils[1]));
      drawLine(PaintBox, clRed, round(xWert + (quartils[1] - zahlen[index][0]) * eineLaengenEinheit), getHeight[4], round(xWert +
        (quartils[1] - zahlen[index][0]) * eineLaengenEinheit), getHeight[5]);

        //Boxplot an sich
      drawLine(PaintBox, clBlack, xWert, getHeight[6], round(xWert + (quartils[0] - zahlen[index][0]) * eineLaengenEinheit), getHeight[6]);
      drawLine(PaintBox, clBlack, round(xWert + (quartils[0] - zahlen[index][0]) * eineLaengenEinheit), getHeight[4], round(xWert +
        (quartils[1] - zahlen[index][0]) * eineLaengenEinheit), getHeight[4]);
      drawLine(PaintBox, clBlack, round(xWert + (quartils[0] - zahlen[index][0]) * eineLaengenEinheit), getHeight[5], round(xWert +
        (quartils[1] - zahlen[index][0]) * eineLaengenEinheit), getHeight[5]);
      drawLine(PaintBox, clBlack, round(xWert + (quartils[1] - zahlen[index][0]) * eineLaengenEinheit), getHeight[6], FWidth - 80, getHeight[6]);

      //Skala
      for i := 0 to round(zahlen[index][Length(zahlen[index])-1]-zahlen[index][0]) do
        drawLine(PaintBox, clBlack, round(xWert + i * eineLaengenEinheit), getHeight[7], round(xWert + i * eineLaengenEinheit), getHeight[8]);
      drawLine(PaintBox, clBlack, xWert, getHeight[9], FWidth-80, getHeight[9]);
      end;
  end;
Findet ihr einen Fehler? Langsam verzweifle ich daran und kann mir nicht erklären woran es liegen kann :/
Miniaturansicht angehängter Grafiken
fehler_1.png   fehler_2.png  
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
7.178 Beiträge
 
Delphi XE4 Professional
 
#2

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 11:57
Hallo,
OK, für den schlechten Stil hast Du dich schon entschuldigt

Aber:
for i := 0 to round(zahlen[index][Length(zahlen[index])-1]-zahlen[index][0]) do
und
round(xWert + i * eineLaengenEinheit), getHeight[8

Wer soll das verstehen?
Bitte benutze eine lokale Variablen und F5/F7/F8 und Strg+F5.

Ich kenne dieses Boxplots erst mal gar nicht.
Und einen Datensatz habe ich auch nicht gefunden.
Woran erkennt man, dass die Boxplots einen gleichen/unterschiedlichen Datensatz haben?

Du hattest ja geschrieben, dass es in C++ bereits funktionierte.
Gehe doch den C++ und den Delphi-Code schrittweise durch und vergleiche die Variableninhalte.
Heiko

Geändert von hoika (24. Apr 2019 um 12:05 Uhr)
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
355 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 12:01
Du rundest Gleitkommawerte auf Ganzzahlen, da kann es schon mal passieren, dass zwei Werte, die in der Dezimaldarstelllung gleich aussehen und als Nachkommateil .5 haben in der Binärdarstellung leicht unterschiedlich sind, so das einer nach oben und einer nach unten gerundet wird. Vielleicht ist das dein Problem...
Peter Below
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
569 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 12:14
Findet ihr einen Fehler? Langsam verzweifle ich daran und kann mir nicht erklären woran es liegen kann :/
Ich kann es erklären, warum du den Fehlr nicht finden kannst SCNR.

Deine Methode ist viel zu lang und komplex. Mache mehrere kleinere daraus, z.B. trenne die Berechnung und das Malen.
Und dann wie hoika schon schrieb debugge.
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.046 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 12:32
Ohne den Source im Einzelnen angesehen zu haben, habe ich folgenden Verdacht:
Es gibt globale Variablen. Die Prozeduren gehören zu keinem Objekt und es wird in den Prozeduren auf die globalen Variablen zugegriffen. Bei jedem Repaint besteht die Gefahr, dass Werte aus den globalen Variablen verwendet werden, die zum anderen "Datensatz" gehören. Die Folge ist, dass mit falschen Werten gezeichnet wird.
Peter
  Mit Zitat antworten Zitat
Pytroxis

Registriert seit: 12. Apr 2019
46 Beiträge
 
#6

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 13:05
Wer soll das verstehen?
Bitte benutze eine lokale Variablen und F5/F7/F8 und Strg+F5.
Das Problem was ich hierbei habe ist, dass die Variablen in einer anderen Procedure verwendet werden müssen (-> Sortieren des Datensatzes, errechnen des medians, der Quartils etc.). Danach werden sie erst zum zeichnen verwendet (in einer anderen Funktion). Demnach wüsste ich nicht wie ich auf lokale Variablen setzen soll außer vielleicht der lokale Variable den Wert der globalen zuzuweisen (-> andere Möglichkeit sehe ich gerade nicht, korrigiere mich bitte falls ich falsch liege).

Ich kenne dieses Boxplots erst mal gar nicht.
Und einen Datensatz habe ich auch nicht gefunden.
Woran erkennt man, dass die Boxplots einen gleichen/unterschiedlichen Datensatz haben?
Ein Boxplots ist das was du im Anhang gesehen hast (-> grafische Darstellung einer Verteilung).
Die Datensätze sind in zahlen gespeichert und sie werden durch den Nutzer eingeben oben in meinem Fall waren die Datensätze:
Delphi-Quellcode:
zahlen[0] := [0,1,2,3,4,5]
zahlen[1] := [0,1,2,3,4,6]
Der unterschied war hierbei die 5 bzw. 6 sprich das Maximum.
Im oberen Bild sieht man, dass beide Boxplots richtig dargestellt werden sofern die Datensätze gleich sind aber bei unterschiedlichen Datensätzen der obere Boxplot "verkrüppelt" ist.

Du hattest ja geschrieben, dass es in C++ bereits funktionierte.
Gehe doch den C++ und den Delphi-Code schrittweise durch und vergleiche die Variableninhalte.
Witzige Geschichte, dass kann ich nicht machen. Das ursprüngliche Programm war fertig, korrekt, als ich dann mit umschreiben auf Delphi soweit fertig war, wollte mein Lehrer, dass ich noch das vergleichen hinzufüge und dabei gibt es jetzt halt die Probleme.

Du rundest Gleitkommawerte auf Ganzzahlen, da kann es schon mal passieren, dass zwei Werte, die in der Dezimaldarstelllung gleich aussehen und als Nachkommateil .5 haben in der Binärdarstellung leicht unterschiedlich sind, so das einer nach oben und einer nach unten gerundet wird. Vielleicht ist das dein Problem...
Probeweise habe ich mal alle round durch trunc ersetz, da somit dieser Fehler ja nicht mehr auftreten dürfte.
Allerdings tritt er immer noch auf und es hat sich nichts verändert. Aber prinzipiell ist die Idee mit trunc statt round gar nicht so schlecht.


Deine Methode ist viel zu lang und komplex. Mache mehrere kleinere daraus, z.B. trenne die Berechnung und das Malen.
Und dann wie hoika schon schrieb debugge.
Aber wie soll ich es denn weiter trennen? Die einzige Möglichkeit die ich sehe wären Arrays (-> Mit den Rechnungen etc.) und diesen dann an eine Funktion zum zeichnen weiterzugeben oder hast du eine bessere Idee?


Ohne den Source im Einzelnen angesehen zu haben, habe ich folgenden Verdacht:
Es gibt globale Variablen. Die Prozeduren gehören zu keinem Objekt und es wird in den Prozeduren auf die globalen Variablen zugegriffen. Bei jedem Repaint besteht die Gefahr, dass Werte aus den globalen Variablen verwendet werden, die zum anderen "Datensatz" gehören. Die Folge ist, dass mit falschen Werten gezeichnet wird.
Die Globalen Variablen werden eigentlich nur einmal verändert und zwar beim sortieren des Datensatzes.
In der Zeichnen Funktion werden ausschließlich lokale Variablen verwendet bzw. überschrieben, es werden nur aus den globalen Variablen gelesen, demnach dürften die globalen Variablen nicht verändert worden sein.


Ich habe die Datensätze auch mehrfach kontrolliert und getestet ob diese verändert werden o.ä. und das wurden sie nicht, daher wundert mich das ganze ja so sehr, dass die Darstellung einmal mit gleichen Datensätzen geht und das andere mal mit unterschiedlichen nicht mehr.
Werde jetzt mal debuggen und mich später nochmal melden
  Mit Zitat antworten Zitat
Pytroxis

Registriert seit: 12. Apr 2019
46 Beiträge
 
#7

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 13:10
Ich habe jetzt noch nicht gedebuggt aber mir ist folgende aufgefallen:
Bisher waren die Datensätze immer
Delphi-Quellcode:
zahlen[0] := [1,2,3,4,5]
zahlen[1] := [1,2,3,4,6]
Dabei war dann der erste Boxplot verkrüppelt.
Nun habe ich die Datensätze einfach mal getauscht:
Delphi-Quellcode:
zahlen[0] := [1,2,3,4,6]
zahlen[1] := [1,2,3,4,5]
Und so werden beide ganz normal angezeigt.

Das wundert mich jetzt noch viel mehr

Edit:
Bitte benutze eine lokale Variablen und F5/F7/F8 und Strg+F5.
Das debuggen hat wirklich geholfen!
Habe meinen Fehler gefunden und jetzt fühle ich mich ziemlich dumm -_-
Habe vergessen die Variablen für Quartils und Median auch auf mehrere Boxplots auszulegen. Werde das jetzt mal ändern aber daran liegt es vermutlich.

Edit2:
Es lag tatsächlich an den Variablen, jetzt fühle ich mich wirklich dumm -_-

Geändert von Pytroxis (24. Apr 2019 um 14:13 Uhr)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
7.178 Beiträge
 
Delphi XE4 Professional
 
#8

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 14:04
Hallo,
geht doch.

die Quartils und Median sahen für mich eh schon etwas komisch aus,
die hatte ich auch im Verdacht ...

Der Debugger ist Dein bester Freund.
Heiko

Geändert von hoika (24. Apr 2019 um 14:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.315 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 14:31
Edit2:
Es lag tatsächlich an den Variablen, jetzt fühle ich mich wirklich dumm -_-
Nicht dumm! Klüger als vorher

Sherlock
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
Pytroxis

Registriert seit: 12. Apr 2019
46 Beiträge
 
#10

AW: Seltsames Verhalten einer Funktion

  Alt 24. Apr 2019, 15:27
Hallo,
geht doch.

die Quartils und Median sahen für mich eh schon etwas komisch aus,
die hatte ich auch im Verdacht ...

Der Debugger ist Dein bester Freund.
Merk ich mir für die Zukunft


Nicht dumm! Klüger als vorher

Sherlock
JaJa
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 05:24 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf