Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Sierpinski Dreieck mit Lazarus (https://www.delphipraxis.net/177715-sierpinski-dreieck-mit-lazarus.html)

ThePhilosopher 22. Nov 2013 15:31

Sierpinski Dreieck mit Lazarus
 
Hallo liebe Leute,
Ich muss für die Schule, genauer gesagt für meine GFS in Mathe, ein Sierpinski Dreieck programmieren.
Ich habe mir dazu heute ein paar Gedanken gemacht und war eigentlich der Meinung einen guten Lösungsweg gefunden zu haben.
Ich habe euch unten mal den Code komplett auskommentiert und die Fehlerhafte Stelle markiert.
An dieser Stelle gibt Lazarus immer die Fehlermeldung "Got Double, Excpectet LongInt" aus.
Ich versteh die ganze Sache nicht weil die Variable den gleichen Wert enthält wie eine andere in der gleichen Rechnung auch und dort wird kein Fehler ausgegeben.
Kann mir jemand helfen??
Gruß
TP
Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
    E: Integer; //Anzahl der Dreiecke pro Ebene
    NH: Integer; //Nenner des Bruchs der die Y Koordinate angibt
    ZH: Integer; //Zähler des Bruchs der die Y Koordinate angibt
    NW: Integer; //Nenner des Bruchs der die X Koordinate angibt
    AW: Integer; //gibt die Anzahl der Wiederholungen an
    a: Integer;  //Wert für Grundseite des Dreiecks
    h: Integer;  //Wert für Höhe des Dreiecks
    Procedure Sierpinski;
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject); //Prozedur die aufgerufen wird wenn der Button geklickt wird
begin
  Canvas.Polygon([Point(0, h), Point(a div 2, 0), Point(a, h)]);
  NH := 3;                                     //
  ZH := 1;                                     //
  NW := 4;                                     //
  AW := StrToInt(Edit1.Text);                  //
  E := 1;                                     //Weißt den Variablen Startwerte zu
  Sierpinski;                                  //Ruft die Prozedur "Sierpinski" auf, in der das gewünschte Sierpinski Dreieck erzeugt wird
end;

procedure TForm1.FormCreate(Sender: TObject); //Prozedur die aufgerufen wird sobald das Fenster entsteht
begin
  a := Image1.Width; //Weißt "a" den Breiten Wert der Fläche "Image1" zu
  h := Image1.Height; //Weißt "h" den Höhen Wert der Fläche "Image1" zu
end;

procedure TForm1.Sierpinski;
var I, II: Integer;

begin
  For I := 1 to AW do  //For-Schleife, die dafür sorgt, dass die gewünschte Zahl an Ebenen erzeugt wird
    begin
      For II := 1 to E do
        begin
          Canvas.MoveTo(1/NW*a, (ZH/NH)*h);   //
          Canvas.LineTo(2/NW*a, (ZH+1)/NH*h); //
          Canvas.LineTo(3/NW*a, (ZH/NH)*h);   //
          Canvas.LineTo(1/NW*a, (ZH/NH)*h);   [COLOR="Red"] //In diesem Rechen Block wird immer bemängelt das "h" ein Double wäre, bei "a" das den gleichen Wert enthält jedoch nicht ??? [/COLOR]
        end;
      E := E*3;
      NW := NW*2;
      NH := NH*2;
      ZH := ZH*2+1;
    end;
end;

end.

himitsu 22. Nov 2013 15:47

AW: Sierpinski Dreieck mit Lazarus
 
h, bzw. das Ergebnis dieser Berechnung ist nunmal eine Fießkommazahl (hier Double), denn du nutzt ja auch "/", bzw. rundest das Ergebnis nicht.

Medium 22. Nov 2013 15:50

AW: Sierpinski Dreieck mit Lazarus
 
Der Fehler müsste eigentlich auch schon in den Aufrufen davor kommen, weil eine Division mit "/" in Delphi bzw. FPC immer einen Extended bzw. Double zurück liefert. Das "h" ist also auch nicht das eigentliche Problem, sondern der Teil davor (bzw. der gesamte Ausdruck dann, weil der dann ebenfalls Extended/Double wird, sobald ein Operand dies ist. Auch wenn dieser Operand das Ergebnis einer Zwischenrechnung ist.)

Am Rande: zuweisen, nicht zuweißen. Ich bekomme da immer Augenkrebs, wird oft falsch gemacht. Bla, Kinkerlitzchen, bin da bloß empfindlicher als nötig :)

ThePhilosopher 22. Nov 2013 16:23

AW: Sierpinski Dreieck mit Lazarus
 
Danke für die Antworten.
Hätte es einen Einfluss auf das Ergebnis wenn ich mit "div" statt mit"/" teilen würde?

Edit: Ich hab's jetzt grad mal mit div probiert. Da gibt er zwar keine Fehlermeldung aus, das Programm tut aber nichts wenn man es ausführt.
Hat jemand ne Idee? :)

himitsu 22. Nov 2013 17:00

AW: Sierpinski Dreieck mit Lazarus
 
Zitat:

Zitat von ThePhilosopher (Beitrag 1237099)
Edit: Ich hab's jetzt grad mal mit div probiert. Da gibt er zwar keine Fehlermeldung aus, das Programm tut aber nichts wenn man es ausführt.
Hat jemand ne Idee? :)

Es kommt drau an was du genau machen willst.

Wie schon erwähnt, rundet DIC ganzzahlig, was dann Folgendem entspricht.
Zitat:

(ZH div NH) * h = Trunc(ZH / NH) * h
vermutlich:
- Rechnung umstellen (erst mal und dann durch)
- oder anders runden

ThePhilosopher 22. Nov 2013 18:11

AW: Sierpinski Dreieck mit Lazarus
 
Das Problem ist, dass ich die genauen Angaben eigentlich brauche weil, dass Dreieck sonst nicht präzise gezeichnet wird.
Gibt es den keine andere Möglichkeit außer Canvas um Linien auszugeben?

himitsu 22. Nov 2013 18:21

AW: Sierpinski Dreieck mit Lazarus
 
Wie gesagt
- Rechnung umstellen > erst mal und dann durch (DIV)
- oder anders runden > Delphi-Referenz durchsuchenRound drausen drumrum

LineTo kann eh nur ganzzahlige Positionieren, also muß man sowieso auf ganze Pixel runden, aber das sollte hier eh reichen.

Medium 23. Nov 2013 04:26

AW: Sierpinski Dreieck mit Lazarus
 
Zunächst ist himitsus Tipp schon mal ein großer Knackpunkt. Das sollte dir schon einen guten Sprung nach vorne geben. Wenn es dann noch zu grob für dich ist:
Du kannst nicht genauer zeichnen als ein Pixel groß ist. Du brauchst die reellen Werte zumindest nicht zum Weiterrechnen, so dass von den Zahlen her an sich alles okay sein dürfte. Aber auf halbe Pixel malen funktioniert einfach nicht. Ausser du benutzt eine Lib, die das insofern unterstützt, als dass sie reelle Koordinaten mittels Anti-Aliasing entsprechend auf umliegende Pixel verteilt. Von Hause aus hat Lazarus da glaube ich nichts, und der Genaugkeitsgewinn ist auch nur scheinbar. (Sieht meistens besser aus, aber technisch gesehen ist nichts gewonnen.)
Ich weiss nicht ob die Graphics32 Lib auch für Lazarus verfügbar ist, aber z.B. die könnte besagtes Zeichnen mit reellen Koordinaten. Allerdings braucht deren Benutzung auch ein gutes Stück Einarbeitung.
Fazit: Wenn du feinere Strukturen gut abgebildet haben willst, musst du einfach größer zeichnen. (Bei Fraktalen gibt es da fieserweise kein "Ende", bei dem man dann alles gesehen hat ;))

himitsu 23. Nov 2013 08:08

AW: Sierpinski Dreieck mit Lazarus
 
Im Moment macht er es ja scheinbar so
Delphi-Quellcode:
Canvas.MoveTo(1 div NW * a, (ZH div NH) * h);
.

Warum eigentlich, die selbe Rechnung, einmal (X) mit Klammern und dann wieder (Y) ohne Klammern?
Ich hoffe malm daß hier / und div gleichwertig behandelt wird, wie das *, so daß hier so oder so von links nach rechts aufgelöst wird.

Wenn man erst Dividiert und dann erst Multipliziert, nachdem abgerundet wurde, dann ist das Ergebnis natürlich immer nur ein ganzes Vielfaches des Multiplikators.
- also entweder nicht ganzzahlig Teilen (ohne Abrundenunden) und erst ganz am Ende entsprechend runden
- oder erst die Multiplikation (hier notfalls auf einen möglichen Integerüberlauf achten) und danach ganzzahlig Dividieren (also inkl. Abrunden oder entsprechend zusätzlich Runden)

ThePhilosopher 23. Nov 2013 11:00

AW: Sierpinski Dreieck mit Lazarus
 
Hallo zusammen,
danke erstmal für die ganzen Tipps.
Ich hab's jetzt tatsächlich so gemacht wie du gesagt hattest: Zuerst multiplizieren und alles mit "round" runden.
Das Programm läuft dann auch und es wird auch etwas dargestellt.
Das ist leider aber noch Meilenweit von dem entfernt was ich eigentlich wollte.
Mir ist dadurch ein ganz anderes Problem in meinem Code klar geworden, das es jetzt erstmal zu lösen gilt.
Ich denke die Darstellung mit round würde mir vollkommen reichen.
Ich war mir nur nicht sicher ob die Werte sich nicht dauerhaft verändern, da ich mit ihnen immer weiter rechnen im Verlauf der Schleifen.
Ich denke meine Frage ist beantwortet :)
Danke!
Gruß
TP


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:57 Uhr.
Seite 1 von 2  1 2      

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