Regula Falsi - Verfahren zum finden von Nullstellen

  • geschlossen
  • C#

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Regula Falsi - Verfahren zum finden von Nullstellen

    hiho leutz
    ich hab ein konsolen prog geschriebn das nullstellen von polynomen x-ten grades ermittelt...
    das ganze ist kommentiert:

    PHP-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq; //nur bei Visual C# 2008
    4. using System.Text;
    5. using System.Security.Cryptography; //Namespace, der für die Zufallsfunktion notwendig ist
    6. namespace Regula_Falsi__Polynom
    7. {
    8. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    9. * +
    10. * Programm zur Ermittlung einer Nullstelle eines Polynoms +
    11. * mittels Regula Falsi +
    12. * außerdem wird ein Vergleich auf die Anzahl der Rechenschritte +
    13. * bei dem Halbierungsverfahren vorgenommen +
    14. * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    15. */
    16. class Program
    17. {
    18. //---------------------------------------------------------- Anfang der Zuweisung des 1. x-Wertes (f(x) ist negativ)
    19. static double Random_neg_x(double[] Koeffizient, int grad) // Variablen a,b,c werden als Parameter
    20. { // angenommen, um f(x) zu errechnen
    21. double neg_x, neg_y;
    22. do
    23. {
    24. neg_y = 0;
    25. // Create a byte array to hold the random value.
    26. byte[] randomNumber = new byte[1];
    27. // Create a new instance of the RNGCryptoServiceProvider.
    28. RNGCryptoServiceProvider Ran_neg_x = new RNGCryptoServiceProvider();
    29. // Fill the array with a random value.
    30. Ran_neg_x.GetBytes(randomNumber);
    31. neg_x = Convert.ToDouble(randomNumber[0]); // Erzeugung der Zufallszahl neg_x
    32. for (int i = 0; i < grad + 1; i++)
    33. {
    34. neg_y = neg_y + Koeffizient[i] * Math.Pow(neg_x, grad - i); // Zuweisung des negativen y Wertes
    35. }
    36. } while (neg_y >= 0); // solange bis f(neg_x) negativ ist
    37. return neg_x; // Rückgabe von neg_x
    38. }
    39. //---------------------------------------------------------- Anfang der Zuweisung des 2. x-Wertes (f(x) ist positiv)
    40. static double Random_pos_x(double[] Koeffizient,int grad) // Variablen a,b,c werden als Parameter
    41. { // angenommen, um f(x) zu errechnen
    42. double pos_x,pos_y;
    43. do
    44. {
    45. pos_y = 0;
    46. // Create a byte array to hold the random value.
    47. byte[] randomNumber = new byte[1];
    48. // Create a new instance of the RNGCryptoServiceProvider.
    49. RNGCryptoServiceProvider Ran_pos_x = new RNGCryptoServiceProvider();
    50. // Fill the array with a random value.
    51. Ran_pos_x.GetBytes(randomNumber);
    52. pos_x = Convert.ToDouble(randomNumber[0]); // Erzeugung der Zufallszahl pos_x
    53. for (int i = 0; i < grad + 1; i++)
    54. {
    55. pos_y = pos_y + Koeffizient[i] * Math.Pow(pos_x, grad - i); // Zuweisung der positiven y Wertes
    56. }
    57. } while (pos_y < 0); // solange bis f(pos_x) positiv ist
    58. return pos_x; // Rückgabe von pos_x
    59. }
    60. //---------------------------------------------------------- Anfang der Ermittlung des nächsten x-Wertes
    61. static double Next_x(double neg_x, double neg_y, double pos_x, double pos_y) // Annahme von Koordinaten der Punkte als Parameter
    62. {
    63. double new_x, m , n;
    64. m = (pos_y - neg_y) / (pos_x - neg_x); // Berechnung der Steigung = y1-y2/x1-x2
    65. n = pos_y - m * pos_x; // Berechnung des n = y-m*x
    66. new_x = (-n) / m; // Berechnung der Nullstelle der Geraden
    67. return new_x; // Rückgabe der neuen Nullstelle
    68. }
    69. //---------------------------------------------------------- Anfang des Hauptprogramms(Ermittlung der Nullstelle mittel Regula Falsi)
    70. static void Main(string[] args)
    71. {
    72. double new_x, new_y, neg_x, neg_y, pos_y, pos_x, AnzNachkommastellen, g;
    73. int grad;
    74. // g = Genauigkeit in Form von 0,0...1
    75. // new_x, new_y = Koordinaten des neuen errechneten Punktes
    76. // grad = Funktion x.Grades
    77. Console.WriteLine("\nProgramm zum Finden von Nullstellen von Polynomen");
    78. Console.WriteLine("Geben sie nur Polynome ein die auch min. eine Nullstelle haben.\nAnsonsten erzeugt das Programm eine endlos Schleife.");
    79. Console.Write("\nBitte geben sie den Grad des Polynoms an: ");
    80. grad = Convert.ToInt32(Console.ReadLine());
    81. double[] Koeffizient = new double[grad + 1];
    82. //Array mit den Koeffizienten
    83. for (int i = 0; i < grad + 1; i++)
    84. {
    85. Console.Write("\n{0}. Koeffizient: ",i+1);
    86. Koeffizient[i] = Convert.ToDouble(Console.ReadLine());
    87. }
    88. Console.Write("\nBitte geben Sie nun die gewünschte Anzahl der Nachkommastellen <10 an: ");
    89. AnzNachkommastellen = Convert.ToDouble(Console.ReadLine()); // Zuweisung der Anzahl der Nachkommastellen
    90. Console.Write("\n");
    91. if (AnzNachkommastellen == 0) // Wenn AnzNachkommastellen 0 ist, funktioniert
    92. { // die Rechnung nicht, deshalb die Überprüfung
    93. g = 0;
    94. }
    95. else
    96. {
    97. g = 1 / (Math.Pow(10, AnzNachkommastellen)); // Umwandlung der AnzNackommastellen in Genauigkeit
    98. } // mit der Form 0,0...1
    99. if (true) // Überprüfen auf Vorhandensein einer Nullstelle************************************muss noch gemacht werden
    100. {
    101. double const_neg_x, const_pos_x; // Initialisierung der Variable für den Vergleich
    102. const_neg_x = Random_neg_x(Koeffizient,grad); // Ermittlung eines x für das gilt: f(x)<0
    103. const_pos_x = Random_pos_x(Koeffizient,grad); // Ermittlung eines x für das gilt: f(x)>0
    104. neg_x = const_neg_x;
    105. pos_x = const_pos_x;
    106. int counter = 0; // Initialisierung der Zähl Variable
    107. do
    108. {
    109. neg_y = 0;
    110. pos_y = 0;
    111. new_y = 0;
    112. counter++; // Hochzählen der Zählers
    113. for (int i = 0; i < grad + 1; i++)
    114. {
    115. neg_y = neg_y + Koeffizient[i]*Math.Pow(neg_x,grad-i); // Zuweisung des negativen y Wertes
    116. }
    117. for (int i = 0; i < grad + 1; i++)
    118. {
    119. pos_y = pos_y + Koeffizient[i]*Math.Pow(pos_x,grad-i); // Zuweisung der positiven y Wertes
    120. }
    121. new_x = Next_x(neg_x, neg_y, pos_x, pos_y); // Ermittlung des nächsten x Wertes
    122. for (int i = 0; i < grad + 1; i++)
    123. {
    124. new_y = new_y + Koeffizient[i] * Math.Pow(new_x, grad - i); // Zuweisung des nächsten y Wertes
    125. }
    126. if (new_y < 0)
    127. {
    128. neg_x = new_x; // Wenn der neue x Wert kleiner 0 ist, dann
    129. } // ist neg_x = new_x
    130. else
    131. {
    132. pos_x = new_x; // Wenn der neue x Wert kleiner 0 ist, dann
    133. } // ist pos_x = new_x
    134. Console.Write("y-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_y, pos_y);
    135. // Ausgabe des y Intervalls; die Zahlen sind nach der Genauigkeit formatiert
    136. Console.WriteLine("\t\tx-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_x, pos_x);
    137. // Ausgabe des x Intervalls; die Zahlen sind nach der Genauigkeit formatiert
    138. } while (Math.Abs(new_y) > g); // solage der Betrag von new_y größer 0,0...1 ist
    139. Console.WriteLine("\nx = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_x);
    140. Console.WriteLine("y = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_y);
    141. Console.WriteLine("Genauigkeit = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", g);
    142. Console.WriteLine("Anzahl der Rechendurchläufe = {0}\n\n\n\n", counter);
    143. // Ausgabe des Ergebnisses und Infos
    144. Halbierungsverfahren(const_neg_x, const_pos_x, AnzNachkommastellen, Koeffizient, g, grad);// Aufruf der Funktion zum Vergleich
    145. }
    146. Console.ReadLine();
    147. }
    148. //---------------------------------------------------------- Anfang der Ermittlung der Nullstelle mittels Halbierungsverfahren
    149. static void Halbierungsverfahren(double const_neg_x, double const_pos_x, double AnzNachkommastellen, double[] Koeffizient, double g, int grad)
    150. {
    151. double neg_x, neg_y, pos_x, pos_y, new_x, new_y;
    152. int counter = 0;
    153. neg_x = const_neg_x;
    154. pos_x = const_pos_x;
    155. do
    156. {
    157. neg_y = 0;
    158. pos_y = 0;
    159. new_y = 0;
    160. counter++;
    161. for (int i = 0; i < grad + 1; i++)
    162. {
    163. neg_y = neg_y + Koeffizient[i] * Math.Pow(neg_x, grad - i); // Zuweisung des negativen y Wertes
    164. }
    165. for (int i = 0; i < grad + 1; i++)
    166. {
    167. pos_y = pos_y + Koeffizient[i] * Math.Pow(pos_x, grad - i); // Zuweisung der positiven y Wertes
    168. }
    169. new_x = (pos_x + neg_x) / 2; //Zuweisung des Mittelwertes
    170. for (int i = 0; i < grad + 1; i++)
    171. {
    172. new_y = new_y + Koeffizient[i] * Math.Pow(new_x, grad - i); // Zuweisung des nächsten y Wertes
    173. }
    174. if (new_y < 0)
    175. {
    176. neg_x = new_x;
    177. }
    178. else
    179. {
    180. pos_x = new_x;
    181. }
    182. Console.Write("y-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_y, pos_y);
    183. Console.WriteLine("\t\tx-Intervall: [{0:F' + AnzNachkommastellen + '} ; {1:F' + AnzNachkommastellen + '}]", neg_x, pos_x);
    184. } while (Math.Abs(new_y) > g);
    185. Console.WriteLine("\nx = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_x);
    186. Console.WriteLine("y = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", new_y);
    187. Console.WriteLine("Genauigkeit = {0:F" + Convert.ToString(AnzNachkommastellen) + "}", g);
    188. Console.WriteLine("Anzahl der Rechendurchläufe = {0}", counter);
    189. }
    190. }
    191. }
    Alles anzeigen

    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
    [SIZE="4"][FONT="Comic Sans MS"]Ich knalle keine Menschen ab, sonder treffe die Hitbox eines Polygonmodells.[/FONT][/SIZE]
  • 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.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Broken Sword () aus folgendem Grund: Doppelpost

  • 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?
    [SIZE="4"][FONT="Comic Sans MS"]Ich knalle keine Menschen ab, sonder treffe die Hitbox eines Polygonmodells.[/FONT][/SIZE]
  • 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:
    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.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von wasawasa ()

  • Hab auch noch ein Beispiel für ein einfaches Diagramm dazugehängt.
    Das ist der Code für das Formular "Form1"

    Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Drawing;
    6. using System.Linq;
    7. using System.Text;
    8. using System.Windows.Forms;
    9. using ZedGraph;
    10. namespace ZedGraphTest
    11. {
    12. public partial class Form1 : Form
    13. {
    14. // Abgeschrieben von der Seite "CodeProject"
    15. public Form1()
    16. {
    17. InitializeComponent();
    18. }
    19. // Auf 'Resize' reagieren
    20. private void Form1_Resize(object sender, EventArgs e)
    21. {
    22. SetSize();
    23. }
    24. // SetSize() ist ausgelagert. So kann men es von
    25. //überall her benutzen
    26. private void SetSize()
    27. {
    28. zg1.Location = new Point(10, 10);
    29. // Den Rand festlegen
    30. // Da kann man auch noch Raum für Buttons und Eingabefelder
    31. // lassen.
    32. zg1.Size = new Size(ClientRectangle.Width - 20,
    33. ClientRectangle.Height - 20);
    34. }
    35. // Den 'Load' - event verarbeiten
    36. private void Form1_Load(object sender, EventArgs e)
    37. {
    38. // Das ZedGraph Objekt einrichten
    39. CreateGraph(zg1);
    40. // Das Control in das Fenster einpassen
    41. SetSize();
    42. }
    43. // Eine eingache Grafik ausgeben
    44. private void CreateGraph(ZedGraphControl zgc)
    45. {
    46. // Eine Referenz zum Arbeiten besorgen
    47. GraphPane myPane = zgc.GraphPane;
    48. // Titel setzen
    49. myPane.Title.Text = "Ein kleiner Test\n(Freesoft-Board)";
    50. myPane.XAxis.Title.Text = "Die X-Achse";
    51. myPane.YAxis.Title.Text = "Die Y-Achse";
    52. // Make up some data arrays based on the Sine function
    53. double x, y1, y2;
    54. PointPairList list1 = new PointPairList();
    55. PointPairList list2 = new PointPairList();
    56. for (int i = 0; i < 36; i++)
    57. {
    58. x = (double)i + 5;
    59. y1 = 1.5 + Math.Sin((double)i * 0.2);
    60. y2 = 3.0 * (1.5 + Math.Sin((double)i * 0.2));
    61. list1.Add(x, y1);
    62. list2.Add(x, y2);
    63. }
    64. // Kurve mit der Punktform 'Diamant' erzeugen
    65. LineItem myCurve = myPane.AddCurve("Bla",
    66. list1, Color.Red, SymbolType.Diamond);
    67. // Kurve mit der Punktform 'Circle' erzeugen
    68. LineItem myCurve2 = myPane.AddCurve("Blub",
    69. list2, Color.Blue, SymbolType.Circle);
    70. // Ein Refresh der Achsen von ZedGraph anfordern
    71. zgc.AxisChange();
    72. }
    73. }
    74. }
    Alles anzeigen


    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.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von wasawasa ()