Regula Falsi - Verfahren zum finden von Nullstellen geschlossen 

Status
Für weitere Antworten geschlossen.

xparet0209

Registered +
Registriert
Okt. 2007
Beiträge
435
hiho leutz
ich hab ein konsolen prog geschriebn das nullstellen von polynomen x-ten grades ermittelt...
das ganze ist kommentiert:
PHP:
using System;
using System.Collections.Generic;
using System.Linq; //nur bei Visual C# 2008
using System.Text;
using System.Security.Cryptography; //Namespace, der für die Zufallsfunktion notwendig ist

namespace Regula_Falsi__Polynom
{
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* +
* Programm zur Ermittlung einer Nullstelle eines Polynoms +
* mittels Regula Falsi +
* außerdem wird ein Vergleich auf die Anzahl der Rechenschritte +
* bei dem Halbierungsverfahren vorgenommen +
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/


class Program
{

//---------------------------------------------------------- Anfang der Zuweisung des 1. x-Wertes (f(x) ist negativ)
static double Random_neg_x(double[] Koeffizient, int grad) // Variablen a,b,c werden als Parameter 
{ // angenommen, um f(x) zu errechnen
double neg_x, neg_y;
do
{
neg_y = 0;

// Create a byte array to hold the random value. 
byte[] randomNumber = new byte[1];

// Create a new instance of the RNGCryptoServiceProvider. 
RNGCryptoServiceProvider Ran_neg_x = new RNGCryptoServiceProvider();

// Fill the array with a random value. 
Ran_neg_x.GetBytes(randomNumber);

neg_x = Convert.ToDouble(randomNumber[0]); // Erzeugung der Zufallszahl neg_x
for (int i = 0; i < grad + 1; i++)
{
neg_y = neg_y + Koeffizient[i] * Math.Pow(neg_x, grad - i); // Zuweisung des negativen y Wertes
}
} while (neg_y >= 0); // solange bis f(neg_x) negativ ist 
return neg_x; // Rückgabe von neg_x

}

//---------------------------------------------------------- Anfang der Zuweisung des 2. x-Wertes (f(x) ist positiv)
static double Random_pos_x(double[] Koeffizient,int grad) // Variablen a,b,c werden als Parameter 
{ // angenommen, um f(x) zu errechnen
double pos_x,pos_y;
do
{
pos_y = 0;
// Create a byte array to hold the random value.
byte[] randomNumber = new byte[1];

// Create a new instance of the RNGCryptoServiceProvider. 
RNGCryptoServiceProvider Ran_pos_x = new RNGCryptoServiceProvider();

// Fill the array with a random value.
Ran_pos_x.GetBytes(randomNumber);

pos_x = Convert.ToDouble(randomNumber[0]); // Erzeugung der Zufallszahl pos_x
for (int i = 0; i < grad + 1; i++)
{
pos_y = pos_y + Koeffizient[i] * Math.Pow(pos_x, grad - i); // Zuweisung der positiven y Wertes 
}
} while (pos_y < 0); // solange bis f(pos_x) positiv ist
return pos_x; // Rückgabe von pos_x

}


//---------------------------------------------------------- Anfang der Ermittlung des nächsten x-Wertes
static double Next_x(double neg_x, double neg_y, double pos_x, double pos_y) // Annahme von Koordinaten der Punkte als Parameter
{ 
double new_x, m , n;
m = (pos_y - neg_y) / (pos_x - neg_x); // Berechnung der Steigung = y1-y2/x1-x2
n = pos_y - m * pos_x; // Berechnung des n = y-m*x
new_x = (-n) / m; // Berechnung der Nullstelle der Geraden
return new_x; // Rückgabe der neuen Nullstelle

}

//---------------------------------------------------------- Anfang des Hauptprogramms(Ermittlung der Nullstelle mittel Regula Falsi)
static void Main(string[] args)
{
double new_x, new_y, neg_x, neg_y, pos_y, pos_x, AnzNachkommastellen, g;

int grad;
// g = Genauigkeit in Form von 0,0...1
// new_x, new_y = Koordinaten des neuen errechneten Punktes
// grad = Funktion x.Grades

Console.WriteLine("\nProgramm zum Finden von Nullstellen von Polynomen");
Console.WriteLine("Geben sie nur Polynome ein die auch min. eine Nullstelle haben.\nAnsonsten erzeugt das Programm eine endlos Schleife.");
Console.Write("\nBitte geben sie den Grad des Polynoms an: ");
grad = Convert.ToInt32(Console.ReadLine());
double[] Koeffizient = new double[grad + 1];
//Array mit den Koeffizienten
for (int i = 0; i < grad + 1; i++)
{
Console.Write("\n{0}. Koeffizient: ",i+1);
Koeffizient[i] = Convert.ToDouble(Console.ReadLine()); 
}
Console.Write("\nBitte geben Sie nun die gewünschte Anzahl der Nachkommastellen  AnzNachkommastellen = Convert.ToDouble(Console.ReadLine()); // Zuweisung der Anzahl der Nachkommastellen 
Console.Write("\n");


if (AnzNachkommastellen == 0) // Wenn AnzNachkommastellen 0 ist, funktioniert
{ // die Rechnung nicht, deshalb die Überprüfung
g = 0;
}
else
{
g = 1 / (Math.Pow(10, AnzNachkommastellen)); // Umwandlung der AnzNackommastellen in Genauigkeit
} // mit der Form 0,0...1


if (true) // Überprüfen auf Vorhandensein einer Nullstelle************************************muss noch gemacht werden
{

double const_neg_x, const_pos_x; // Initialisierung der Variable für den Vergleich 
const_neg_x = Random_neg_x(Koeffizient,grad); // Ermittlung eines x für das gilt: f(x) const_pos_x = Random_pos_x(Koeffizient,grad); // Ermittlung eines x für das gilt: f(x)>0 
neg_x = const_neg_x;
pos_x = const_pos_x;
int counter = 0; // Initialisierung der Zähl Variable 


do
{
neg_y = 0;
pos_y = 0;
new_y = 0;
counter++; // Hochzählen der Zählers
for (int i = 0; i < grad + 1; i++)
{
neg_y = neg_y + Koeffizient[i]*Math.Pow(neg_x,grad-i); // Zuweisung des negativen y Wertes
}
for (int i = 0; i < grad + 1; i++)
{
pos_y = pos_y + Koeffizient[i]*Math.Pow(pos_x,grad-i); // Zuweisung der positiven y Wertes 
}

new_x = Next_x(neg_x, neg_y, pos_x, pos_y); // Ermittlung des nächsten x Wertes
for (int i = 0; i < grad + 1; i++)
{
new_y = new_y + Koeffizient[i] * Math.Pow(new_x, grad - i); // Zuweisung des nächsten y Wertes 
}


if (new_y < 0)
{
neg_x = new_x; // Wenn der neue x Wert kleiner 0 ist, dann
} // ist neg_x = new_x
else
{
pos_x = new_x; // Wenn der neue x Wert kleiner 0 ist, dann
} // ist pos_x = new_x

Console.Write("y-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_y, pos_y);
// Ausgabe des y Intervalls; die Zahlen sind nach der Genauigkeit formatiert 
Console.WriteLine("\t\tx-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_x, pos_x);
// Ausgabe des x Intervalls; die Zahlen sind nach der Genauigkeit formatiert

} while (Math.Abs(new_y) > g); // solage der Betrag von new_y größer 0,0...1 ist

Console.WriteLine("\nx = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_x);
Console.WriteLine("y = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_y);
Console.WriteLine("Genauigkeit = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", g);
Console.WriteLine("Anzahl der Rechendurchläufe = {0}\n\n\n\n", counter);
// Ausgabe des Ergebnisses und Infos

Halbierungsverfahren(const_neg_x, const_pos_x, AnzNachkommastellen, Koeffizient, g, grad);// Aufruf der Funktion zum Vergleich



}


Console.ReadLine();
}





//---------------------------------------------------------- Anfang der Ermittlung der Nullstelle mittels Halbierungsverfahren
static void Halbierungsverfahren(double const_neg_x, double const_pos_x, double AnzNachkommastellen, double[] Koeffizient, double g, int grad)
{
double neg_x, neg_y, pos_x, pos_y, new_x, new_y;
int counter = 0;

neg_x = const_neg_x;
pos_x = const_pos_x;

do
{
neg_y = 0;
pos_y = 0;
new_y = 0;
counter++;
for (int i = 0; i < grad + 1; i++)
{
neg_y = neg_y + Koeffizient[i] * Math.Pow(neg_x, grad - i); // Zuweisung des negativen y Wertes
}
for (int i = 0; i < grad + 1; i++)
{
pos_y = pos_y + Koeffizient[i] * Math.Pow(pos_x, grad - i); // Zuweisung der positiven y Wertes 
}
new_x = (pos_x + neg_x) / 2; //Zuweisung des Mittelwertes
for (int i = 0; i < grad + 1; i++)
{
new_y = new_y + Koeffizient[i] * Math.Pow(new_x, grad - i); // Zuweisung des nächsten y Wertes 
}
if (new_y < 0)
{
neg_x = new_x;
}
else
{
pos_x = new_x;
}
Console.Write("y-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_y, pos_y);
Console.WriteLine("\t\tx-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_x, pos_x);
} while (Math.Abs(new_y) > g);


Console.WriteLine("\nx = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_x);
Console.WriteLine("y = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_y);
Console.WriteLine("Genauigkeit = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", g);
Console.WriteLine("Anzahl der Rechendurchläufe = {0}", counter);

}
}
}
mein lehrer meint das regula falsi schneller als das halbierungsverfahren ist
wenn ich dann aber das ergebnis sehe ist der counter bei dem halbierungsverfahren immer kleiner...
wieso ist das so?^^

und kann ich den zufalls generator am anfang nicht optimieren?
es wäre geil wenn ich das nicht nur in einem konsolen programm hätte
sondern den graphen der funktion ausgeben könnte
leider hab ich kein plan wie man eine solche oberfläche programmiert...
könntet ihr mir da tipps gebn?
ich hab bisher nur konsolenanwendungen geschrieben...

mfg xparet0209
 
Hallo, im ersten Schritt mal zur Grafik. Mit C# lässt sich mittels der Bibliothek "zedgrap" sehr einfach was erstellen. Main Page - ZedGraphWiki
Es ist ein sehr guter Kompromiss zwischen Lernkurve und optischem Ergebnis :-).

Noch eine Bemerkung: Es steht unter LGPL und kostet nix.

Die Bisektion eignet sich für folgende Fälle:
* Ein Vorzeichenwechsel liegt im gegebenen Intervall vor und die Funktion ist stetig
* Die Startwerte der klassischen Verfahren (Newton-Verfahren, Regula Falsi)
liegen nicht hinreichend nah genug an der Nullstelle, so dass dort keine lokale
Konvergenz eintritt
* Mehrfache Nullstellen mindern die Konvergenzgeschwindigkeit der klassischen
Verfahren

Nachteile der Bisektion:
* Bei einfachen Fällen (streng monotone Funktion) ist sie langsamer als ein
quadratisch konvergentes Verfahren
* Ohne Vorzeichenwechsel im gegebenen Intervall sind Zusatzprüfungen
notwendig, um ein lokales Minimum von einer Nullstelle zu unterscheiden

Eine generelle Aussage über die Geschwindigkeit ist nach meiner Ansicht nicht immer zutreffend. Es ist immer auch eine Frage der Rahmenbedingungen und der Anfangswerte.
 
Zuletzt bearbeitet von einem Moderator:
nja da ich bis her nur konsolenanwendungen programmiert habe
bräuchte ich eine kleine einstiegshilfe
wie gehe ich mit der library um?
und wie erstell ich eingabe fenster?
 
Ich bin gerade beruflich völlig ausgelastet.
Wenn es ein bisschen Zeit hat, dann kann ich einige Tipps und Besipiele dazu schreiben.

Hab jetzt mal den Anfang gemacht:


Vorbereitungen für die Verwendung von ZedGraph

Erst mal besorgt man sich die Software, welche umsonst ist:
http://sourceforge.net/project/showfiles.php?group_id=114675
Am Anfang sollte es reichen die DLL (zedgraph dll only) herunterzladen.
Ich habe die Version V.5.1.5 geladen.

Die Bibliothek habe ich ausgepackt und unter E:\VisualStudio\Lib\zedgraph_dll_v5.1.5
abgelegt.

Im nächsten Schritt startet man sein Visual Studio (bei mir 2008) und legt ein
C#-Projekt (Windows Forms Anwendung) an. Ich habe dem Projekt den Namen
ZedGraphTest gegeben.

Jetzt muss man die Bibliothek nur noch im Projekt verfügbar machen.


# "Projekt->Verweis hinzufügen..." aufrufen.
# Dann geht ein Fenster auf mit dem Titel "Verweis hinzufügen". Dort auf das Tab "Durchsuchen" gehen.
# Auf das Verzeichnis mit den DLLs navigieren und die DLLs "ZedGrap.dll", "ZedGrap.Web.dll" einbinden.
# Jetzt in die Entwurfsansicht für Formulare wechseln. (Sollte defaulmäßig "Form1" sein)
# Wenn noch nicht offen, die Toolbox aufmachen. (Menüpunkt "Ansicht->Toolbox")
# Ein Rechtsklick auf die Toolbox lässt ein Kontextmenü erscheinen. Dort den Punkt "Element auswählen ..." aktivieren.
# Unter dem Tab".Net Framework-Komponenten" auf "Durchsuchen" klicken.
# Auch hier wieder die beiden DLLs annavigieren und einbinden.
# Jetzt sollte mit etwas Suchen das "ZedGraphControl" in der Toolbox zu finden sein.
# Linke Maustaste, Drag und Drop auf das Formular. Jetzt liegt das Control auf dem Formular.
# mit der rechten Maustaste auf das ZegGraph Control klicken und das Kontextmenü "Eigenschaften" aufmachen.
# Das Control in zg1 umbenennen (Das ist der übliche Name, also benenne ich es auch immer um ...).
# In den Code von Form1 noch das Statement "using ZedGraph;" einbauen.

Das ist die minimalste Konfiguration um mit dem ZedGraph COntrol zu spielen.
 
Zuletzt bearbeitet von einem Moderator:
Hab auch noch ein Beispiel für ein einfaches Diagramm dazugehängt.
Das ist der Code für das Formular "Form1"

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZedGraph;

namespace ZedGraphTest
{
public partial class Form1 : Form
{
// Abgeschrieben von der Seite "CodeProject"

public Form1()
{
InitializeComponent();
}

// Auf 'Resize' reagieren

private void Form1_Resize(object sender, EventArgs e)
{
SetSize();
}

// SetSize() ist ausgelagert. So kann men es von
//überall her benutzen

private void SetSize()
{
zg1.Location = new Point(10, 10);
// Den Rand festlegen
// Da kann man auch noch Raum für Buttons und Eingabefelder
// lassen.

zg1.Size = new Size(ClientRectangle.Width - 20,
ClientRectangle.Height - 20);
}

// Den 'Load' - event verarbeiten

private void Form1_Load(object sender, EventArgs e)
{
// Das ZedGraph Objekt einrichten

CreateGraph(zg1);

// Das Control in das Fenster einpassen
SetSize();
}

// Eine eingache Grafik ausgeben

private void CreateGraph(ZedGraphControl zgc)
{
// Eine Referenz zum Arbeiten besorgen

GraphPane myPane = zgc.GraphPane;

// Titel setzen
myPane.Title.Text = "Ein kleiner Test\n(Freesoft-Board)";
myPane.XAxis.Title.Text = "Die X-Achse";
myPane.YAxis.Title.Text = "Die Y-Achse";

// Make up some data arrays based on the Sine function

double x, y1, y2;
PointPairList list1 = new PointPairList();
PointPairList list2 = new PointPairList();
for (int i = 0; i < 36; i++)
{
x = (double)i + 5;
y1 = 1.5 + Math.Sin((double)i * 0.2);
y2 = 3.0 * (1.5 + Math.Sin((double)i * 0.2));
list1.Add(x, y1);
list2.Add(x, y2);
}

// Kurve mit der Punktform 'Diamant' erzeugen

LineItem myCurve = myPane.AddCurve("Bla",
list1, Color.Red, SymbolType.Diamond);

// Kurve mit der Punktform 'Circle' erzeugen

LineItem myCurve2 = myPane.AddCurve("Blub",
list2, Color.Blue, SymbolType.Circle);

// Ein Refresh der Achsen von ZedGraph anfordern

zgc.AxisChange();

}

}
}

Jetzt brauche ich ein Feedback, ob es Dir hilft und ob ich weitermachen soll.
Es kostet micht Zeit, von der ich sehr wenig habe.
Wenn Du es nicht verwenden kannst, dann kann ich mir die Zeit sparen.
 
Zuletzt bearbeitet von einem Moderator:
Status
Für weitere Antworten geschlossen.

Ähnliche Themen

W
  • Gesperrt
  • geschlossen 
Antworten
1
Aufrufe
2K
Zurück
Oben Unten