Nullstellensuche einer Funktion per Näherungsverfahren

Tiyen

Mitglied
Dies gilt solange bis yMitte nahe 0 ist.

Wie kann man das denn in Java schreiben ?
Es soll ja nur bis 5 Nachkommastellen genau sein, ich glaube dafür gibt es aber keine Funktion oder ?

Java:
import java.util.*;

public class Nullstellensuche {
	public static void main(String[] args) {

		double links, rechts, ymitte;

		Scanner input = new Scanner(System.in);

		System.out.println("**********Nullstellensuche**********");

		System.out.print("Linke Intervallgrenze eingeben : ");
		links = input.nextDouble();

		System.out.print("Rechte Intervallgrenze eingeben : ");
		rechts = input.nextDouble();
		input.close();

                // Ausgabe nur um zu sehen ob die Werte richtig sind
		System.out.println(function(links));
		System.out.println(function(rechts));

		// Wenn beide y-Werte < 0 sind gibt es keine Nullstellen
		if (function(links) < 0 && function(rechts) < 0) {
			System.out
					.println("Innerhalb dieses Intervalls gibt es keine Nullstellen.");
		}

		// Wenn beide y-Werte > 0 sind gibt es mehrere Nullstellen
		else if (function(links) > 0 && function(rechts) > 0) {
			System.out
					.println("Innerhalb dieses Intervalls gibt keine Nullstellen.");
		}

		// In allen anderen Fällen, rufe die Funktion intervall() auf
		else {
			ymitte = (links + rechts) / 2;
			intervall(links, rechts, ymitte);
			System.out.println("Die Nullstelle liegt nahe: " + ymitte);
		}
	}

	// Berechnung der y-Werte
	public static double function(double intervallwert) {

		return (intervallwert + 1) * (intervallwert + 1) - 1;
	}

	// Methode zur Verkleinerung des Intervalls
	public static double intervall(double links, double rechts, double ymitte) {

		while (ymitte ) {// Hier wird immer eine Endlossschleife ausgeführt wenn ich ymitte < oder > 0 setze
			ymitte = (links + rechts) / 2;
			System.out.println(ymitte);
			if (ymitte > 0) {
				rechts = ymitte;
			} else if (ymitte < 0) {
				links = ymitte;
			}
		}
		return ymitte;
	}
}
 

HonniCilest

Erfahrenes Mitglied
Kleiner Tipp,
überlege dir vorher wirklich genau, was du tun willst, das ist reine Mathematik, alles andere ist nur eine Umsetzung dessen!

Grundsätzlich gilt: y = f(x) = (x + 1)² - 1
f(x) ist in deinem Programm function(x), also kannst du schreiben y = function(x).

y soll kleiner wie 0.00001 werden, aber du willst x am Ende wissen und nicht y! links und rechts sind auch x, vielleicht nennst du dir diese zur Übersichtlichkeit um...

Nachdem du das gelesen hast schau z.B. nochmal auf folgende Zeilen:
Java:
ymitte = (links + rechts) / 2;
//...
System.out.println("Die Nullstelle liegt nahe: " + ymitte);

Das kann doch nicht passen oder :)

Java:
if(wert > -0.00001 && wert < 0.00001)
    //Auf 5 Stellen genau bei 0

Oder:
Java:
if(Math.abs(wert) < 0.00001) {}
 

Tiyen

Mitglied
Vielen Dank HonniCilest für deine Hilfe, aber irgendwie bekomme ich es noch nicht so auf die Reihe. Ich weiß einfach nicht wie ich den Intervall verkleinern kann.

Also die Funktion (x+1)^2-1 hat an -2 und 0 eine Nullstelle. Wenn ich als Intervall nun angebe:

xlinks = -10
xrechts = -1

Dann befindet sich in diesem Intervall ja die Nullstelle -2.
Ich frage mich nur wann ich welche Seite x ich verschieben muss.
Habe es mit der Mitte versucht, das man die immer halbiert, aber das muss ich ja mit beiden Seiten machen, nur da komme ich einfach nicht drauf welche Bedingung für xlinks oder xrechts gelten muss.
 

HonniCilest

Erfahrenes Mitglied
Das mit der Hälfte ist ja richtig, aber du willst die Hälfte der x-Werte, also xm = (xl + xr) / 2 anstatt ym. Davon brauchst du wieder ym = f(xm). Nun betrachtest du ym. Wenn ym nahe 0 ist kannst du glücklich sein. xm ist dann dein gesuchter Wert, wo die Nullstelle ist. Ansonsten schaust du dir das Vorzeichen von ym an. Du ersetzt das Wertepaar xy mit dem gleichen y-Vorzeichen wie ym und suchst dann wieder die Mitte zwischen xl und xr für ein neues xm und ein neues ym.

Vielleicht malst du dir eine Skizze auf, damit du das nachvollziehen kannst.
 

Tiyen

Mitglied
Ok so langsam komme ich dahinter. Im Debugger verkleinert er das Intervall auch bis xlinks = -2.125,
aber irgendwo ist da noch ein Fehler den ich einfach nicht finde.

Java:
	// Methode zur Verkleinerung des Intervalls
	        public static double intervall(double xl, double xr, double xmid, double ymid) {

		xmid = (xl+xr)/2;
		ymid=function(xmid);
		
		
		while (ymid > 0) { // Wusste nicht genau welche Bedingung ich nutzen sollte

			if(Math.abs(xl) < 0.00001){
				return xl;
			}
			xmid = (xl + xr) / 2; // Neue Mitte des Intervalls
			ymid = function(xmid); 

			if (ymid == 0) { // Falls ym = 0 dann Nullstelle gefunden bei xm
				return xmid;
			}
			if (ymid > 0) { // 
				xl = xmid;
			}
		}
		return xl;
	}
}
 

HonniCilest

Erfahrenes Mitglied
Wird schon besser...

Aber anstatt einer while-Schleife, würde ich eine do-while-Schleife verwenden, dann musst du den Teil mit der Mitte nicht 2x schreiben. Ansonsten reicht es, wenn du while(true) schreibst, mit return kommst du dann aus der Schleife raus. Wieso überprüfst du x auf Nähe 0? y muss nahe null sein! Ansonsten kannst du das gleiche Vorzeichen beispielsweise so überprüfen:

Java:
if(yl * ym > 0) {
// gleiches Vorzeichen, ersetze xl und yl durch die Werte der Mitte, ansonsten ersetze xr und yr
}
 

Tiyen

Mitglied
ok jetzt habe ich gerade komplett den Faden verloren.

Java:
	public static double intervall(double yl, double yr, double xl, double xr, double xmid, double ymid) {
		
		do {
			xmid = (xl + xr) / 2; // Neue Mitte des Intervalls
			ymid = function(xmid); 

			if (ymid > 0) { // 
				xl = xmid;
			}
			yl = function(xl);
			if(yl*ymid > 0){
				xl = xmid;
				yl = xmid;
			}
			else{
				xr = xmid;
				yr = xmid;
			}
			return ****;
		}while(true);
	}

Stimmt da eigentlich überhaupt noch was ? Habe nämlich so das Gefühl, dass ich nur Mist produziere :/