# Berechnungen führen zur falschen Bewertung der Existenz einer Lösung



## waverider (18. Okt 2012)

Hallo an alle,
ich bin neu, studiere seit kurzem Informatik und habe ein Problem mit einer Aufgabe die wir lösen sollen.

Und ja, ich hab auch schon die sufu benutzt, 
hab auch 2 ähnliche Threads gefunden, nur leider hat es mir nicht zu einer Lösung geholfen.
Vielleicht fehlt mir auch nur die richtige Vokabel um was passendes zu finden :/

Also folgendes:

Es geht im Prinzip um eine simple p-q berechnung.
Die Zahlen a, b und c sollen in der Form ax²+bx+c=0 eingegeben werden.

Weiterhin soll das Programm ausgeben ob es nur eine, zwei oder keine Lösungen gibt.
Daher überprüfe ich anschließend das Ergebniss nach der Form oben. Bei einfachen Werten funktioniert das auch perfekt.
Allerdings scheint die Prüfung bei folgenden Werten für a, b und c nicht zu funktionieren:
a=1, b=-4,2, c=4,21

Meine Vermutung ist ja, dass da schon intern irgendwo gerundet wird, und er daher bei der Prüfung nicht auf ==0 bzw !=0 kommt.

Kann mir jemand ein Tipp geben woran das liegt?
Achja, für Tips zum Programmierstil wäre ich auch dankbar 


Und bitte nehmt mich nicht direkt auseinander,
studiere erst seit ein paar wochen ^^

[Java]
import java.util.Scanner;

public class Quadratic {

	public static void main(String[] args) {

		Scanner console = new Scanner(System.in);
		double a, b, c;

		System.out.println("Bitte geben sie Ihre Werte ein: ");
		System.out.print("a = ");
		a = console.nextDouble();
		System.out.print("b = ");
		b = console.nextDouble();
		System.out.print("c = ");
		c = console.nextDouble();

		quadratic(a, b, c);

		console.close();

	}

	public static void quadratic(double a, double b, double c) {
		double x1=0, x2=0;

		//Ist a != 0 ?
		if (a!=0)	{
			x1 = ((-b+Math.sqrt((b*b-4*a*c)))/2*a);					// Lösen nach p-q-Formel
			System.out.println(x1);									// <-- Später noch entfernen!!!
			x2 = ((-b-Math.sqrt((b*b-4*a*c)))/2*a);					// Lösen nach p-q-Formel
			System.out.println(x2);									// <-- Später noch entfernen!!!
			//Zwei Lösungen
			if (a*x1*x1+b*x1+c==0 && (a*x2*x2+b*x2+c==0) )	{
				System.out.println("Erste Lösung = "+round1(x1));
				System.out.println("Zweite Lösung = "+round1(x2));
			}
			else	{
				//Keine Lösung
				if (a*x1*x1+b*x1+c!=0 && (a*x2*x2+b*x2+c!=0) )	{
					System.out.println("Keine reele Lösung");
				}
				//Nur eine Lösung
				else	{					
					if (a*x1*x1+b*x1+c==0)	{
						System.out.println("Lösung: "+round1(x1));
					}
					else	{
						if (a*x2*x2+b*x2+c==0)	{
							System.out.println("Lösung: "+round1(x2));
						}
					}
				}
			}
		}
		else	{
			System.out.println("a muss ungleich 0 sein");
		}																																				
	}

	public static double round1(double value) { 
	    if (Double.isNaN(value)) return value; 
	    if (Double.isInfinite(value)) return value; 
	    return Math.round(value * 10) / 10.0; 
	} 

}

[/Java]

btw, 
für den fall dass ich mich nicht eindeutig ausgedrückt habe,
hier nen bild von der aufgabenstellung:
http://www.abload.de/img/pqtnud0.jpg


----------



## Landei (18. Okt 2012)

Das wichtigste zuerst: Wenn 
	
	
	
	





```
b*b-4*a*c
```
 negativ ist und du ziehst daraus die Wurzel, gibt es eine Exception. Du musst diesen Fall ("keine Lösungen") *vor* der Berechnung prüfen, damit es nicht dazu kommen kann.


----------



## waverider (18. Okt 2012)

guter tipp,
hab im code oben ne neue if-abfrage hinzugefügt


```
public static void quadratic(double a, double b, double c) {
		double x1=0, x2=0;
		
		//Ist a != 0 ?
		if (a!=0)	{
			if (b*b-4*a*c<0)	{
				System.out.println("Keine reele Lösung");
			}
			else	{
				x1 = ((-b+Math.sqrt((b*b-4*a*c)))/2*a);					// Lösen nach p-q-Formel
				System.out.println(x1);									// <-- Später noch entfernen!!!
				x2 = ((-b-Math.sqrt((b*b-4*a*c)))/2*a);					// Lösen nach p-q-Formel
				System.out.println(x2);									// <-- Später noch entfernen!!!
				//Zwei Lösungen
				if (a*x1*x1+b*x1+c==0 && (a*x2*x2+b*x2+c==0) )	{
					System.out.println("Erste Lösung = "+round1(x1));
					System.out.println("Zweite Lösung = "+round1(x2));
				}
				else	{
					//Keine Lösung
					if (a*x1*x1+b*x1+c!=0 && (a*x2*x2+b*x2+c!=0) )	{
						System.out.println("Keine reele Lösung");
					}
					//Nur eine Lösung
					else	{					
						if (a*x1*x1+b*x1+c==0)	{
							System.out.println("Lösung: "+round1(x1));
						}
						else	{
							if (a*x2*x2+b*x2+c==0)	{
								System.out.println("Lösung: "+round1(x2));
							}
						}
					}
				}
			}
		}
		else	{
			System.out.println("a muss ungleich 0 sein");
		}																																				
	}
[/Java]

allerdings fange ich jetzt an mich zu fragen ob die werte auf dem aufgabenblatt falsch sind.
da ist z.B. für a=0,1 b=0,6 und c=0,9 eine Lösung von -3 angegeben... obwohl die wurzel ja negativ ist...
```


----------



## TryToHelp (18. Okt 2012)

> a=0,1 b=0,6 und c=0,9


 Hat keine Lösung also würde ich dem Lösungsblatt mal nicht vertrauen, rechne entweder deine ergebnisse Händisch oder such dir im i-Net passende Rechner zum überptüfen


----------



## Deros (18. Okt 2012)

> Allerdings scheint die Prüfung bei folgenden Werten für a, b und c nicht zu funktionieren:
> a=1, b=-4,2, c=4,21



mit den Werten kommt halt tatsächlich x1 = 0.0 und x2 =-8.881784197001252E-16 raus und x2 ist dann halt nicht genau 0. Sprich du musst dein "ist gleich" etwas ungenauer definieren da beim Wurzeziehen es immer zu Rundungsfehlern kommen kann.


----------



## waverider (18. Okt 2012)

> a=0,1 b=0,6 und c=0,9



für diese Werte habe ich jetzt mal den Prof angeschrieben, 
mal sehen was er dazu sagt.

dennoch bekomme ich noch nicht die richtigen ergebnisse bei

a=1 b=-4,2 c=4,21
lösungen sollen 2,5 und 1,7 sein.

mein rechner hat das ausgerechnet
2.5472135954999584
1.652786404500042

gibt aber nur den ersten wert als richtig zurück.
ich nehme an, das da die prüfung nicht stimmt, weil intern gerundet wurde ?!


----------



## waverider (18. Okt 2012)

Deros hat gesagt.:


> mit den Werten kommt halt tatsächlich x1 = 0.0 und x2 =-8.881784197001252E-16 raus und x2 ist dann halt nicht genau 0. Sprich du musst dein "ist gleich" etwas ungenauer definieren da beim Wurzeziehen es immer zu Rundungsfehlern kommen kann.



ok, 
sowas dachte ich mir ja schon.

aber wie soll ich das denn ungenauer definieren?
dazu fällt mir nämlich nichts ein :/


----------



## Deros (18. Okt 2012)

auf jedenfall würde ich deine berechnung um auf 0 zu prüfen in eine variable auslagern, da du sie im zweifel jeweils 3 mal ausführst.

dann hast du 2 möglichkeiten, entweder du prüfst nicht ob a*x1*x1+b*x1+c!=0 sondern  -0.0000001<a*x1*x1+b*x1+c<0.0000001 oder da du die Rechnung ja eh auslagern sollst machst du darauf nen cast nach int das sollte die Rundungsfehler auch eliminieren


----------



## homer65 (18. Okt 2012)

Mathematisch mußt du prüfen, ob der folgende Ausdruck 
x = c/a - b*b/(4*a*a)
größer, kleiner oder gleich 0 ist.
Mit einem Computer und dem Datentyp double hast du Rundungsfehler.
Im Klartext heißt das, die Prüfung, ob x = 0 ist, funktioniert nicht.
Der Fall x=0 und damit eine Lösung ist so nicht feststellbar.
Immerhin kannst du bei X > 0 und x < 0 noch recht sicher sein.


----------



## Landei (18. Okt 2012)

Kleiner Tipp: Du kannst dir die Lösungen bei Wolfram Alpha anschauen. Da sieht man dann auch, wieso hier ein kleiner Rundungsfehlern zu einem falschen Ergebnis führen kann:

0.1x+0.6x+0.9=0 - Wolfram|Alpha


----------

