WinFuture-Forum.de: C# - Zählen Von Punkten - WinFuture-Forum.de

Zum Inhalt wechseln

Nachrichten zum Thema: Entwicklung
Seite 1 von 1

C# - Zählen Von Punkten


#1 Mitglied ist offline   Oderich 

  • Gruppe: Mitglieder
  • Beiträge: 6
  • Beigetreten: 15. Mai 08
  • Reputation: 0

  geschrieben 15. Mai 2008 - 22:53

Hallo zusammen,
ich habe in Programmieren folgende Aufgabe bekommen "Berechnung von Pi mit Hilfe von Monte-Carlo Algorithmus in C#". Info dazu.
Ich habe schon herausgefunden wie man Kreis und Quadrat zeichnet. Und jetzt kann ich sogar eine beliebige Anzahl an Punkten im Quadrat zufällig erzeugen. Das Problem bei mir ist dass ich nicht weiß wie man die Punkte, die im Kreis bzw. außerhalb liegen, zählen kann. Hat jemand vielleicht eine Idee wie man das macht?
0

Anzeige



#2 Mitglied ist offline   Witi 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.942
  • Beigetreten: 13. Dezember 04
  • Reputation: 43
  • Geschlecht:Männlich
  • Wohnort:Kingsvillage
  • Interessen:Frickeln

geschrieben 16. Mai 2008 - 06:32

Hallo Oderich und willkommen im Forum!

In dem Wiki-Artikel ist doch ein wunderbares Beispiel in Java was du im Prinzip 1 zu 1 nach C# übernehmen kannst.
Hier trotzdem eine kurze Erklärung der wichtigsten Punkte des Algorithmus.
	if (dotx*dotx + doty*doty <= 1) {
	  // Punkt liegt innerhalb des Kreises
	  innerhalb++;
	} else {
	  // Punkt liegt außerhalb des Kreises
	}

Ein Punkt liegt innerhalb des Kreises, wenn die Addition der Quadrate beider Punke unter bzw. gleich 1 sind. Stichwort: Pythagoras und Einheitskreis

Zitat

Der Anteil der innen liegenden Punkte ist gleich π / 4

Das heißt:
Anteil = PI / 4 
PI = Anteil * 4
PI  = (Treffer im Kreis / Gesamtzahl der Punkte) * 4

Fertig :lol:
0

#3 Mitglied ist offline   Oderich 

  • Gruppe: Mitglieder
  • Beiträge: 6
  • Beigetreten: 15. Mai 08
  • Reputation: 0

geschrieben 16. Mai 2008 - 15:05

Hallo Witi, danke für den Antwort!
So habe ich am Anfang auch gedacht. Aber der Quelltext auf der Wikipedia ist eigentlich falsch. Ich erkläre warum.
double dotx = Math.random();

Math.random(); liefert in Java einen zufälligen Wert von 0 bis 1.
if (dotx*dotx + doty*doty <= 1)

Es gibt also 4 Möglichkeiten von dem Ausdruck in Klammern.
dotx doty Wert
0 0 0
0 1 1
1 0 1
1 1 2
(weiß leider nicht wie man Tabelle zeichnet)
Wie man sieht ist die if-Bedingung in 75% der Fälle erfüllt (in 3 von 4 Fällen). Jetzt zu der Formel.
pi = 4*(double)innerhalb/gesamt;
Division innerhalb/gesamt ergibt so im Durchschnitt 3/4. 4* 3/4 = 3. So kriegt man als Ergebnis im Schnitt 3 raus. Ich habe sogar dieses Programm in C# umgeschrieben und getestet, es hat gestimmt - Ergebnis ist tatsächlich ca. 3 und Pi ist doch 3,14... Deswegen bezweifle ich ob man diese Aufgabe so lösen kann.
Und noch was. Mein Quadrat liegt im x-Bereich 10 bis 110, im y-Bereich auch 10 bis 110. Ich hoffe du hast meinen Beitrag verstanden. :D
0

#4 Mitglied ist offline   [Elite-|-Killer] 

  • Gruppe: aktive Mitglieder
  • Beiträge: 762
  • Beigetreten: 02. Oktober 05
  • Reputation: 0
  • Geschlecht:Männlich
  • Wohnort:Passau

geschrieben 16. Mai 2008 - 15:14

"Division innerhalb/gesamt ergibt so im Durchschnitt 3/4. 4* 3/4 = 3. So kriegt man als Ergebnis im Schnitt 3 raus. Ich habe sogar dieses Programm in C# umgeschrieben und getestet, es hat gestimmt - Ergebnis ist tatsächlich ca. 3 und Pi ist doch 3,14... "
Nur so eine Idee von einem Nicht-Mathematiker: Erhöht sich die Genauigkeit nicht, wenn du den Wertebereich erhöhst, also statt 0 und 1 0 und 10 als Gerenze hernimmst und die If-Bedingung dem entsprechend anpasst?
Kann natürlich sein, dass ich was übersehen habe, da ich das Problem jetzt nur mal schnell überflogen habe.

Dieser Beitrag wurde von [Elite-|-Killer] bearbeitet: 16. Mai 2008 - 15:29

0

#5 Mitglied ist offline   Witi 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.942
  • Beigetreten: 13. Dezember 04
  • Reputation: 43
  • Geschlecht:Männlich
  • Wohnort:Kingsvillage
  • Interessen:Frickeln

geschrieben 16. Mai 2008 - 15:15

Zitat

Math.random(); liefert in Java einen zufälligen Wert von 0 bis 1.

Falsch, http://java.sun.com/....h.html#random()

Edit:
OK, zufälliger Wert zwischen 0 und 1 ist zwar richtig, aber folgende Aussage ist falsch, weil eine Gleitkommazahl generiert wird

Zitat

Es gibt also 4 Möglichkeiten von dem Ausdruck in Klammern.


z.B.
0.7956725892881681
0.4217333527782938
0.21466720173159626
0.028101672208614814

0

#6 Mitglied ist offline   Oderich 

  • Gruppe: Mitglieder
  • Beiträge: 6
  • Beigetreten: 15. Mai 08
  • Reputation: 0

geschrieben 16. Mai 2008 - 17:33

Ups, sorry habe gar nicht daran gedacht dass es die Zahlen die in Java erzeugt werden, Gleitpunktzahlen sein können. Habe einfach früher keine Erfahrung mit Java gehabt. :D Vielen Dank für solche wertvolle Hinheise! Das hat mich echt weitergebracht. Jetzt stimmt das Programm einigermaßen.
Ich bekomme als Ergebnis nach 100000 oder sogar Million Punkte als Pi ungefähr 3.12. Ist eine solche Fehlerquote normal oder nicht? Wahrscheinlich muss man den Quadrat größer machen und Ergebnis wird so genauer.

Dieser Beitrag wurde von Oderich bearbeitet: 16. Mai 2008 - 17:34

0

#7 Mitglied ist offline   Oderich 

  • Gruppe: Mitglieder
  • Beiträge: 6
  • Beigetreten: 15. Mai 08
  • Reputation: 0

geschrieben 19. Mai 2008 - 13:33

Ich habe ein weiteres Problem mit dem Programm. Ich weiß nicht wie man den Ergebnis vom Pi auf dem Bildschirm ausgeben könnte. ;) Ich will eigentlich dass es mit Labels und so geht. Irgendwie kann ich nicht die Form für das Zeichnen und die Form mit Buttons gleichzeitig am Bildschirm ausgeben. Und die Form für das Zeichnen ist soweit ich weiß lediglich fürs Zeichnen bestimmt. Vielleicht kann jemand mir dabei helfen. Ich habe noch für mehr Übersicht mein Programm hier angehängt: Angehängte Datei  Pi.rar (28,44K)
Anzahl der Downloads: 246
edit:
Problem wurde gelöst. Lösung: Ergebnis von Pi auf dem Bildschirm als String mit e.Graphics.DrawString zeichnen.

Dieser Beitrag wurde von Oderich bearbeitet: 22. Mai 2008 - 16:47

0

#8 Mitglied ist offline   Oderich 

  • Gruppe: Mitglieder
  • Beiträge: 6
  • Beigetreten: 15. Mai 08
  • Reputation: 0

geschrieben 21. Mai 2008 - 18:07

Ich habe ein weiteres Problem liegt beim Zeichnen von Punkten mit der for-Schleife. Die Punkte werden manchmal so gezeichnet wie es in dem Kopf der for-Schleife angegeben ist und manchmal doppelt so viele Male. Z.B. ich will dass 5 Punkte gezeichnet werden, und es werden manchmal 10 Punkte angezeigt. Ein weiteres Problem das vermutlich aus dem vorgerigem entsteht, liegt in dem Zeichnen von Strings. Beim Debuggen wird der String mit dem Ergebnis von Pi schon dann angezeigt, wenn nicht alle Punkte auf dem Bildschirm zu sehen sind. Am Ende von dem Durchlaufen wird der Ergebnis nochmal angezeigt über dem alten. Das kann nur dann passieren wenn man praktisch aus der Schleife springt und dann wieder zurück. Aber das ist doch unmöglich! Hat jemand die Idee woran das Problem liegt? Ich habe das Programm hier angehängt.
edit:
Meine OnPaint-Methode:
protected override void OnPaint(PaintEventArgs e)
		{
			this.Text = "Pi";
			this.Size = new Size(700, 700);  //this.Size = new Size(1024, 768);
			//this.BackColor = Color.Silver;
			//base.OnPaint(e);
			int xpos;
			int ypos;
			int innerhalb = 0;
			int gesamt = 0;
			decimal pi;
			e.Graphics.DrawEllipse(new Pen(Color.Red), -300, -300, 600, 600);
			e.Graphics.DrawRectangle(new Pen(Color.Blue), 0, 0, 300, 300);
			Random random = new Random();
			Pen pen2 = new Pen(Color.Black);
			for (int i = 1; i <= 10000; i++)
			{
				xpos = random.Next(0, 301);
				ypos = random.Next(0, 301);
				e.Graphics.DrawRectangle(pen2, xpos, ypos, 1, 1);
				if (xpos * xpos + ypos * ypos <= 90000)
				{
					innerhalb++;
				}
				gesamt++;
			}
			pi = (decimal)4 * innerhalb / gesamt;
			string s = pi.ToString();
			Font times = new Font("Times", 15);
			e.Graphics.DrawString("Pi: " + pi + "\nGesamtanzahl der Punkte: " + gesamt + "\nPunkte innerhalb: " + innerhalb, times, Brushes.Black, 400, 100);
		}

Dieser Beitrag wurde von Oderich bearbeitet: 21. Mai 2008 - 19:11

0

#9 Mitglied ist offline   Oderich 

  • Gruppe: Mitglieder
  • Beiträge: 6
  • Beigetreten: 15. Mai 08
  • Reputation: 0

geschrieben 22. Mai 2008 - 16:43

Hab mein Problem gelöst. Das lag daran, dass die OnPaint-Methode manchmal 2 mal aufgerufen wird. So habe ich ein Feld painted erstellt, das überprüfen soll ob die Zeichnung schon stattgefunden hat.
Meine gesamte Klasse:
	public partial class Form1 : Form
	{
		private bool painted = false;	   
		public Form1()
		{
			InitializeComponent();
		}
		private void panel1_Paint(object sender, PaintEventArgs e)
		{
			if (!painted)
			{
				painted = true;
				int xpos;
				int ypos;
				int innerhalb = 0;
				int gesamt = 0;
				decimal pi;
				int punkte = 100000;
				e.Graphics.DrawEllipse(new Pen(Color.Red), -600, -600, 1200, 1200);
				e.Graphics.DrawRectangle(new Pen(Color.Blue), 0, 0, 600, 600);
				Random random = new Random();
				for (int i = 1; i <= punkte; i++)
				{
					xpos = random.Next(0, 601);
					ypos = random.Next(0, 601);
					e.Graphics.FillRectangle(new SolidBrush(Color.Black), xpos, ypos, 1, 1);
					if (xpos * xpos + ypos * ypos <= 360000)
					{
						innerhalb++;
					}
					gesamt++;
				}
				pi = (decimal)4 * innerhalb / gesamt;
				string s = pi.ToString();
				Font times = new Font("Times", 15);
				e.Graphics.DrawString("Gesamtanzahl der Punkte: " + gesamt + "\nPunkte innerhalb: " + innerhalb + "\nPi: " + pi, times, Brushes.Black, 700, 100);
			}

0

Thema verteilen:


Seite 1 von 1

1 Besucher lesen dieses Thema
Mitglieder: 0, Gäste: 1, unsichtbare Mitglieder: 0