AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?
Thema durchsuchen
Ansicht
Themen-Optionen

Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

Ein Thema von mabstudent · begonnen am 13. Nov 2010 · letzter Beitrag vom 15. Nov 2010
Antwort Antwort
mabstudent

Registriert seit: 13. Nov 2010
23 Beiträge
 
#1

Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 15:13
Hallo zusammen,

Ich bin schon seit längerem in eurem Forum unterwegs und bisher mit der Suche ausgekommen, doch dieses mal reicht sie mir leider nicht ganz.
Vorab tut es mir leid dass ich euch das Problem nur aus der Sicht eines Maschinenbaustudenten, der ein Pflichtsemester Informatik absolvieren muss, darstellen kann.


Aufgabe ist folgende:

Grafische Ausgabe von Zufallszahlen --> Bestimmung von PI nach der Monte Carlo Methode


Meine Teilaufgaben sind:
1. Imagefeld erzeugen
2. Viertelkreis mit r=300 darauf zeichnen, Mittelpunkt(0,0)
3. auf Knopfdruck Pixelregen starten
4. auf Knopfdruck Pixelregen stoppen
5. Pixel die zufällig im Viertelkreis landen eine Farbe geben z.B. blau
6. Pixel die außerhalb des Viertelkreises landen eine andere Farbe geben z.B. rot
7. PI ist das Verhältnis der im Viertelkreis liegenden Pixel zu der Gesamtheit der Pixel (PI soll eine 12-stellige Genauigkeit haben)

Mein Struktogramm dazu: siehe Anhang
Mein bisheriger Quelltext:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, Buttons, StdCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    BitBtn1: TBitBtn;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);

  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  b,h,x,y,u,i:integer;


implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
application.ProcessMessages;
u:=0;
Randomize();
image1.Canvas.Brush.color:=clwhite;
image1.Canvas.FillRect(Rect(0,0,b,h));
image1.Canvas.MoveTo(0,300);

  FOR x:=0 TO 300 DO //Viertelkreis zeichnen
    begin
    y:=trunc(sqrt((300*300)-(x*x)));
    image1.canvas.LineTo(x,y);
    end;

end;

procedure TForm1.Button1Click(Sender: TObject); //Zufallszahlen grafisch ausgeben

begin
  application.processmessages; //damit die Anwendung nicht hakt
  FOR i:=0 TO u:=1 DO //lass die Schleife laufen bis u:=1 ist
  x:=random(300); //zufallszahlen erzeugen von 0-300
  y:=random(300);
  IF (sqrt((x*x)+(y*y))<=300) //wurzel aus x^2+y^2 entspricht dem radius des VK
  THEN image1.canvas.pixels[x,y]:=clblue
  ELSE image1.Canvas.Pixels[x,y]:=clred;
end;

end;



procedure TForm1.Button2Click(Sender: TObject);
begin
u:=1;
end;

end.

Folgende Probleme treten hierbei auf:

1. Wie kann ich die Schleife welche Zufallszahlen erzeugt und diese als Pixel auf das Image regnen lässt solange laufen lassen bis ich einen Knopf drücke, der es stoppt?
2. Wie lautet der richtige Quellcode für die Berechnung von PI:=((4*Viertelkreispixel)/Gesamtzahlpixel)? Anders gefragt: Welche Typen müssen die Variablen haben?
Miniaturansicht angehängter Grafiken
pi.png  
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#2

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 15:29
1.) Ein Viertelkreis zeichnen kannst du bestimmt Windows überlassen, so brauchst du keine Schleife.
Delphi-Quellcode:
begin
  Image1.Picture.Bitmap.Canvas.Ellipse(0, -300, 600, 300);
end;
2.) deine For-Schleife ist wahrhaftig etwas sonderbar. Delphi-Pascal != C, deshalb kannst du das nur mit einer WHILE-Struktur machen (Außerdem gibt es einen eleganteren Weg für die Abbrechung (u => Abbr (Boolean):
Delphi-Quellcode:
var i: Integer;
begin
  Abbr := false;
  while not Abbr do
  begin
    Application.ProcessMessages;
    //...
  end;
end;
Dein Abbrechen sieht dann einfach so aus, dass du Abbr auf TRUE setzt.

2. Wie lautet der richtige Quellcode für die Berechnung von PI:=((4*Viertelkreispixel)/Gesamtzahlpixel)? Anders gefragt: Welche Typen müssen die Variablen haben?
PI sollte dann mindestens Single sein (Das reicht IMHO für 12 Nachkommastellen, wenn nicht Double).
Die Variable Viertelkreispixel reicht, wenn sie Integer ist. So viele Pixel und vor allem Zeit hast du gar nicht zur Verfügung (Integer geht bis 2 Mrd). Für Gesamtpixel reicht dann auch Integer. Du kannst diese allerdings beide nicht errechnen, sondern darfst deine Pixelregen-Funktion dahingehend umschreiben, dass die automatisch die entsprechenden Werte aktualisiert.

Bernnhard
Bernhard
Iliacos intra muros peccatur et extra!
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#3

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 16:03
Delphi-Quellcode:
var
  b,h,x,y,u,i:integer; // Hilfe, globale Variablen mit nur einem Buchstaben
Mach' dich mal mit lokalen Variablen vertraut.
Globale Variablen mit nur einem Buchstaben sind eine "Todsünde" für jeden Programmierer.
Beispiel wie man's besser macht:
Delphi-Quellcode:
procedure TForm1.ZeichneMonteCarlo;
var
  x ,y : integer; // Lokale Variablen
begin
  x:=random(300); //zufallszahlen erzeugen von 0-299
  y:=random(300);
  if (sqrt((x*x)+(y*y))<=300) then //wurzel aus x^2+y^2 entspricht dem radius des VK
    image1.canvas.pixels[x,y]:=clblue
  else
    image1.Canvas.Pixels[x,y]:=clred;
end;

Geändert von sx2008 (13. Nov 2010 um 16:04 Uhr) Grund: Code besser formatiert
  Mit Zitat antworten Zitat
mabstudent

Registriert seit: 13. Nov 2010
23 Beiträge
 
#4

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 16:08
Vielen vielen Dank, hätte ich mich mal eher an euch gewandt, an meiner "WirrWarr Schleife" saß ich nämlich mehrere Stunden

Danke auch für den Tipp von sx2008


Deshalb stelle ich jetzt gleich mein nächstes Problem bei dem Programm vor, auch wenn ich beim Rumprobieren viel gelernt hab:

Um PI zu berechnen muss ich ja die Pixel im Viertelkreis zählen und die Pixel im Quadrat, also die Gesamtzahl der Pixel.
Wie kann ich das machen?
Kann ich in meiner Schleife welche den Pixelregen erzeugt folgendes machen:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);

begin
  abbr:=false;
  VKhits:=0; //Anzahl der Pixel im Viertelkreis, zu Anfang :=0
  NVKhits:=0; //Anzahl der Pixel Nicht im Viertelkreis, zu Anfang:=0
  WHILE NOT abbr DO
  begin
  Application.ProcessMessages;
  x:=random(300);
  y:=random(300);
  IF (sqrt((x*x)+(y*y))<=300)
  THEN image1.canvas.pixels[x,y]:=clblue AND inc(VKhits) //Pixel blau färben UND Anzahl aufsummieren
  ELSE image1.Canvas.Pixels[x,y]:=clred AND inc(NVKhits); //Pixel rot färben UND Anzahl aufsummieren
  end;

label1.Caption:=(4*VKhits/(NVKhits+VKhits)); //ausgabe PI




end;
Klar, das habe ich schon probiert und es funktioniert nicht, aber hier könnt ihr denk ich am besten sehen was ich vorhabe: Um PI zu berechnen muss ich irgendwie an die Anzahl der Pixel im Viertelkreis und an die außerhalb kommen. über die suche habe ich rausgefunden das inc() eine funktion zum zählen ist.
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#5

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 16:19
Mehrere Anweisungen kannst du immer mit begin ... end; zusammenfassen.
Also:
Delphi-Quellcode:
if xyz then
begin
  //Anweisungen
  //noch mehr Anweisungen
end;
  Mit Zitat antworten Zitat
mabstudent

Registriert seit: 13. Nov 2010
23 Beiträge
 
#6

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 16:49
...dann bekomme ich den fehler:

'END' erwartet aber 'ELSE' gefunden

Delphi-Quellcode:
begin
  abbr:=false;
  VKhits:=0;
  NVKhits:=0;
  WHILE NOT abbr DO
  begin
  Application.ProcessMessages;
  x:=random(301);
  y:=random(301);
  IF (sqrt((x*x)+(y*y))<=300)
  THEN image1.canvas.pixels[x,y]:=clblue; //Anweisung 1a
       VKhits:=VKhits+1 //weitere Anweisung
  ELSE image1.Canvas.Pixels[x,y]:=clred; //Anweisung 1b
       NVKhits:=NVKhits+1; //weitere Anweisung

  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#7

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 17:35
Delphi-Quellcode:
  THEN
BEGIN
       image1.canvas.pixels[x,y]:=clblue; //Anweisung 1a
       VKhits:=VKhits+1 //weitere Anweisung
END
  ELSE
BEGIN
       image1.Canvas.Pixels[x,y]:=clred; //Anweisung 1b
       NVKhits:=NVKhits+1; //weitere Anweisung
END
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 18:55
Hier haben wir doch ein perfektes Beispiel dafür, warum man Code und Ausgabe trennen sollte.

Die ermittelten Zufallspunkte werden in einem Bitmap gepseichert und nun drängt sich die Frage auf, wie man die Anzahl der Zufallspixel bekommt und die Anzahl der Pixel im Kreissegment.
Das Bitmap beinhaltet ja auch noch die Kreislinie.

Antwort: Geht gar nicht. Durch die Zufallsmethode können auf einem Pixelpunkt des Bitmaps n Zufallspunkte liegen. Wie soll das im Nachhinein gezählt werden? Pixel ist blauer als der andere Blaue?

Also trennen wir das Ganze mal, denn die Berechnung muss auch ohne grafische Ausgabe erfolgen und selbige dient ja nur der Visualisierung.

Zunächst brauchen wir ja einen Speicher für einen Zufallspunkt. Da bietet und Delphi ja passend TPoint an. Da können wir einen x und y Wert abspeichern (was wollen wir mehr).
Wir haben mehrere Punkte, gut wir brauchen eine Liste. Das ist jetzt Geschmackssache, ob man das mit einer verketteten Liste (Pointer) selber baut, ein variables Array benutzt oder das fertige TList oder auch TObjectList .

Jede Liste hat eine Eigenschaft Count und schon weiß man, wieviele Punkte man insgesamt erzeugt hat.

Jetzt fehlt und ein Algorithmus, der berechnen kann, ob ein Punkt innerhalb oder ausserhalb des Kreissegments liegt.

Die Ausgabe erfolgt jetzt anhand genau dieser Liste. Also jeden Pixel wie gewohnt auf das Bitmap klatschen.
Über den Algorithmus, weiß man, ob der Punkt blau oder rot gepinselt werden soll.

BTW das Ergebnis wird umso genauer, je größer man das Zielgebiet macht.
Ein Gebiet mit 10x10 Pixel ergibt ein ungenaues Ergebnis.
1000x1000 wäre schon besser

Bei einer Auflösung mit 10.000x10.000 habe ich aber Probleme mit der Darstellung. Darum hilft jetzt auch die Trennung zwischen Code und Ausgabe, denn die Pixel-Koordinaten werden für die Ausgabe einfach skaliert.
Code:
AusgabeX = Runden( WertX / WertBreite * AusgabeBreite )
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#9

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 13. Nov 2010, 19:02
Hoi,
Ich war mal so nett und habe es programmiert.
Seid nicht böse, weil ich es ihm vorkaue. Mir war sehr langweilig und ich wollte es einmal programmiert haben.
Übrigens finde ich die Monte-Carlo Methode sehr interessant! Sie zeigt, was sich so alles mit Wahrscheinlichkeiten machen lässt xD

@ThreadStarter
Es bringt zwar nicht direkt viel, ne Komplettlösung zu posten, aber immerhin. Wenn du evt. nicht weiterkommst, kannste ja im Quellcode ggf. nachkucken!

Edit:
Übrigens - Codestil = Spaghetticode.

MfG
Miniaturansicht angehängter Grafiken
screenshot.png  
Angehängte Dateien
Dateityp: rar PI.rar (291,2 KB, 25x aufgerufen)
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (13. Nov 2010 um 19:05 Uhr)
  Mit Zitat antworten Zitat
mabstudent

Registriert seit: 13. Nov 2010
23 Beiträge
 
#10

AW: Programm zur Bestimmung von PI - Schleife auf Knopfdruck abbrechen, aber wie?

  Alt 15. Nov 2010, 13:45
Vielen Dank für eure Hilfe!!
  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 01:19 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