C# - Zählen Von Punkten
#1
geschrieben 15. Mai 2008 - 22:53
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?
Anzeige
#2
geschrieben 16. Mai 2008 - 06:32
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
Das heißt:
Anteil = PI / 4 PI = Anteil * 4 PI = (Treffer im Kreis / Gesamtzahl der Punkte) * 4
Fertig
#3
geschrieben 16. Mai 2008 - 15:05
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.
#4
geschrieben 16. Mai 2008 - 15: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
#5
geschrieben 16. Mai 2008 - 15:15
Zitat
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
z.B.
0.7956725892881681 0.4217333527782938 0.21466720173159626 0.028101672208614814
#6
geschrieben 16. Mai 2008 - 17:33
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
#7
geschrieben 19. Mai 2008 - 13:33
Pi.rar (28,44K)
Anzahl der Downloads: 264
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
#8
geschrieben 21. Mai 2008 - 18:07
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
#9
geschrieben 22. Mai 2008 - 16:43
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);
}

Hilfe
Neues Thema
Antworten
Nach oben



