PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java Hilfe bei Klasse zur Berechnung der PQ-Formel


skynetwork
2006-06-26, 20:27:05
hey leute, ich sitz hier gerade an nem programm zum lösen quadratischer gleichungen der form:

ax² + bx + c = 0

prog funzt soweit auch, aber es berechnet leider falsch wie mir scheint. da ich mathematisch ne ziemliche null bin :ulol: und mir bisher auch das proggen noch nich ganz so von der hand flutscht (und ich eigentlich schon stolz bin, daß prog soweit schon am laufen zu haben) meine frage an euch, ob ihr evtl. den fehler seht. ich komm einfach nicht dahinter, wo in der berechnungsklasse nun der fehler ist....

class MeineBerechnung
{

/**
* Beginn der Methode für Formelberechnung
* @param a
* @param p
* @param q
* @param art
* @return temp2
*/
public static double PQFormeln(double a, double p, double q, String art)
{
double wert1 = a;
double wert2 = p;
double wert3 = q;
double temp1;
double temp2 = 0;
String bereich = art;
if (wert1 != 0) // Das Dividieren durch Null Problem wird ausgeschaltet
{
if (wert2 != 0)
{
wert2 = wert2 / wert1; // Der Wert wird in die PQ Form umgewandelt

}
if (wert3 !=0)
wert3 = wert3 / wert1; // Der Wert wird in die PQ Form umgewandelt
}
else //Es koennte auch der Wert2 Null sein.
{
if (wert2 != 0)
wert2 = wert2 / 2;

}

temp1 = hochrechnen(wert2,2);
temp1 = temp1 - wert3;
temp1 = Math.sqrt(temp1); // Zieht die Quadratwurzel

if (bereich == "+") // Für den positiven X Bereich
{
temp2 = temp1 - wert2;
}

if (bereich == "-")
{
temp2 = temp1 + wert2;
}

if (Double.isNaN(temp2) ) // Hier wird überprüft ob es zu einem NotANumber-Fehler kommt. (Wurzel konnte nicht gezogen werden)
{
temp2 = 0; // Eine Null wird als Fehlerabfang gesetzt.
System.out.println("Keine reele Zahl. Lösung des " + bereich+ " x Bereiches nicht möglich.");
}

return temp2; // Ist eine Reele Zahl oder die Null

}

public static double hochrechnen( double wert, int stellen)
{
double wert2 = wert;
for (int i = 1; i <= stellen; i++)
{
wert2 = wert2 * wert;

}
return wert2;
}


eigentlich nix wirklich kompliziertes und der fehler ist bestimmt minimal, aber ich komme zur hölle einfach nicht drauf, wo der stecken könnte :mad:

Trap
2006-06-26, 20:35:48
Zuerstmal:
Man darf bei Fließkommazahlen durch 0 teilen, sowohl durch +0 als auch durch -0. Dabei kommt sogar richtig +inf oder -inf raus (inf=infinity=unendlich).

Dann als zweites:
Strings vergleicht man mit string1.equals(string2), nicht mit ==.

Drittens:
"x hoch y" ist Math.pow(x,y).

skynetwork
2006-06-26, 21:08:50
okidoki, soweit schonmal thx, werd das im prog editieren. aber leider ist mir immernoch nicht klar, wo dann der eigentliche berechnungsfehler liegt oder isses in der tat nur das "durch 0 teilen" problem? :eek:

Trap
2006-06-26, 21:22:40
skynetwork[/POST]']aber leider ist mir immernoch nicht klar, wo dann der eigentliche berechnungsfehler liegt
stringvariable == stringliteral gibt eigentlich immer false und dann bekommt man halt temp2==0 raus.

Coda
2006-06-27, 10:16:27
Trap[/POST]']Zuerstmal:
Man darf bei Fließkommazahlen durch 0 teilen, sowohl durch +0 als auch durch -0. Dabei kommt sogar richtig +inf oder -inf raus (inf=infinity=unendlich).
Das kommt auf das FPU-Statusregister an ;)

HellHorse
2006-06-27, 20:17:25
Trap[/POST]']stringvariable == stringliteral gibt eigentlich immer false
[mischung aus klugscheiss und gefährlichem halbwissen die nichts daran ändert, dass == für Strings in Java extrem schlechter Stil ist]

Ich dachte eigentlich alle Stringliterale in Java würden interned. Das heisst solange man nur Literale bzw. Referenzen auf Literale vergleicht müssten eigentlich Identität und Äquivalenz gleichbedeutend sein.
Solange art also eine Referenz auf ein Literal ist, wüsste es eigentlich funktionieren.

[/mischung aus klugscheiss und gefährlichem halbwissen die nichts daran ändert, dass == für Strings in Java extrem schlechter Stil ist]

Monger
2006-06-27, 20:49:08
HellHorse[/POST]'][mischung aus klugscheiss und gefährlichem halbwissen die nichts daran ändert, dass == für Strings in Java extrem schlechter Stil ist]

Ich dachte eigentlich alle Stringliterale in Java würden interned. Das heisst solange man nur Literale bzw. Referenzen auf Literale vergleicht müssten eigentlich Identität und Äquivalenz gleichbedeutend sein.
Solange art also eine Referenz auf ein Literal ist, wüsste es eigentlich funktionieren.

[/mischung aus klugscheiss und gefährlichem halbwissen die nichts daran ändert, dass == für Strings in Java extrem schlechter Stil ist]

Afaik nur die Strings, die zur Compilezeit bekannt sind. Alle anderen die danach z.B. durch Benutzereingaben erzeugt werden, werden jedesmal als neue Instanz angelegt.
Das "Internen" wie du es nennst ist ja afaik nur eine Performanceverbesserung, weil der Check auf Gleichheit eben rasend schnell geht, ein Vergleich von Buchstabe zu Buchstabe aber unter Umständen sehr langsam. (Und in der "equals" Methode wird üblicherweise erstmal per == geprüft) Deshalb greift man da so viel vor, wie man eben zur Compilezeit kann.

Kabelsalat
2006-06-27, 20:51:51
Warum kein ==? Ich kenne das zwar bloß aus der .Net-Welt, dort stellt das jedoch keinerlei Problem dar, da zwei exakt gleiche Strings auch eine Referenz auf das selbe String-Objekt darstellen (sprich der String wird auch zur Laufzeit "interned"). Das hängt in dem Fall mit dem besonderen Aufbau der String-Klasse zusammen und ist u.a. für die schlechte Performance bei massenweiser Anwendung der Stringverknüpfung verantwortlich - daher exisitiert auch noch der StringBuilder. Ich ging immer davon aus, .Net und Java seien in diesem Punkt defakto identisch - überzeugt mich vom Gegenteil...

/edit: Habe die Situation gerade nochmal reflektiert: Meine vorrausgehende Aussage sollte zwar auch korrekt sein, dass man "==" Anstelle von Equals verwenden kann, liegt aber primär an der Überladung des Operators, sodass intern String.Equals verwendet wird.

Monger
2006-06-27, 21:17:32
@Kabelsalat: die schlechte Performance beim String zusammenfügen liegt daran, dass String immutable ist, und deshalb bei jedem zusammenfügen eine neue String-Instanz gebildet wird. Neue Objekte anzulegen kostet IMMER Zeit, nicht nur wenn es ein String ist.

StringBuilder ist mutable, deshalb hat der das Problem nicht.
Dass es übrigens keine Operatorüberladungen in Java gibt, war eine Sprachentscheidung. Man war der Meinung, dass man damit mehr Unheil als Segen stiftet.

Trap
2006-06-27, 21:18:42
In Java gilt (auch für Strings):
"==" Überprüfung allein auf Identität
".equals" Überprüfung auf Gleichheit

Kabelsalat
2006-06-27, 21:19:25
Monger[/POST]']@Kabelsalat: die schlechte Performance beim String zusammenfügen liegt daran, dass String immutable ist, und deshalb bei jedem zusammenfügen eine neue String-Instanz gebildet wird. Neue Objekte anzulegen kostet IMMER Zeit, nicht nur wenn es ein String ist.

Was wiederum Grundlage für das interning ist.

Monger
2006-06-27, 21:21:46
Trap[/POST]']In Java gilt (auch für Strings):
"==" Überprüfung allein auf Identität
".equals" Überprüfung auf Gleichheit
Danke, aber soweit waren wir schon! :)

Das gilt aber wie gesagt nicht für die interned Strings. Wobei man diese Optimierung wohl wirklich besser ignoriert: Strings werden per equals verglichen, basta!

Trap
2006-06-27, 21:36:11
Monger[/POST]']Das gilt aber wie gesagt nicht für die interned Strings. Wobei man diese Optimierung wohl wirklich besser ignoriert: Strings werden per equals verglichen, basta!
Wenn man sehr bösartig ist kann man auch immer .intern aufrufen und dann per == vergleichen. Aber nicht wundern wenn das Programm nach längerer Zeit mal 1 GB Speicher braucht ;)

HellHorse
2006-06-27, 21:40:18
Monger[/POST]']Afaik nur die Strings, die zur Compilezeit bekannt sind.
Eben Stringliterale, schreib ich ja.
Monger[/POST]']Das "Internen" wie du es nennst ist ja afaik nur eine Performanceverbesserung, weil der Check auf Gleichheit eben rasend schnell geht, ein Vergleich von Buchstabe zu Buchstabe aber unter Umständen sehr langsam.
Was ich mit internen meine ist internen (keine Ahnung wie das auf Deutsch heisst, auf jeden Fall wird der String in die permanent generation geschoben falls nicht schon ein äquivalenter dort ist).
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern()

In Java gilt (auch für Strings):
"==" Überprüfung allein auf Identität
".equals" Überprüfung auf Gleichheit
Aye, und Literale werden interned, also müsste dort Itentität und Gleichheit das Gleiche sein.
@Kabelsalat: die schlechte Performance beim String zusammenfügen liegt daran, dass String immutable ist, und deshalb bei jedem zusammenfügen eine neue String-Instanz gebildet wird. Neue Objekte anzulegen kostet IMMER Zeit, nicht nur wenn es ein String ist.

StringBuilder ist mutable, deshalb hat der das Problem nicht.
Ich sags ja nicht gerne, aber Stringkontatentation verwendet auch einen StringBuilder (resp. StringBuffer in <= 1.4). Schau dir einfach mal den Bytecode an. Bloss ist das entsprechende Makro halt eben selten doof.

Wenn ich mir den hier geposteten Code anschaue (temp1 :rolleyes: ) dann müsste man in Abetracht des Unheils, das man damit anstellen kann und offensichtlich damit angestellt wird, auch Temps verbieten.

Monger
2006-06-28, 09:06:47
HellHorse[/POST]']
Ich sags ja nicht gerne, aber Stringkontatentation verwendet auch einen StringBuilder (resp. StringBuffer in <= 1.4). Schau dir einfach mal den Bytecode an. Bloss ist das entsprechende Makro halt eben selten doof.

Im Ernst? Okay, dann war ich da misinformiert. Das heißt, solange ich nur eine einzige Zuweisung mache à la

String neuerString = "A" + "B" + "C" + "D" + "E";

brauche ich auch keinen StringBuilder zu verwenden.

Btw, schieb den Kommentar bitte nicht Trap unter, das war mein Mist! ;)

HellHorse
2006-06-28, 10:37:12
Monger[/POST]']Im Ernst? Okay, dann war ich da misinformiert. Das heißt, solange ich nur eine einzige Zuweisung mache à la

String neuerString = "A" + "B" + "C" + "D" + "E";

brauche ich auch keinen StringBuilder zu verwenden.
Das ist sowieso kein Problem, da der Compiler das zur Compilezeit berechnet. Aber auch

String neuerString = a + b + c + d + e;

ist kein Problem.
http://img161.imageshack.us/img161/9518/bytecode2sc.th.png (http://img161.imageshack.us/my.php?image=bytecode2sc.png)
Ok, es ginge effizienter, wenn #conctat in String eine variable Anzahl Argumente nehmen würde und man das verwenden würde.

Was higegen ein Problem ist

String s = "";
for (int i = 0; i < 100000; ++i) {
s = s + i; // Hier wird jedes mal ein neuer StringBuilder gemacht.
}

Monger[/POST]']
Btw, schieb den Kommentar bitte nicht Trap unter, das war mein Mist! ;)
srykthx

Thanks to ImageShack for Free Image Hosting (http://imageshack.us)

Monger
2006-06-28, 10:41:49
HellHorse[/POST]']...
http://img161.imageshack.us/img161/9518/bytecode2sc.th.png (http://img161.imageshack.us/my.php?image=bytecode2sc.png)

Mal ne ganz dämliche Frage: wie kann ich denn in Eclipse mir den Byte Code ansehen?

HellHorse
2006-06-28, 10:42:08
Trap[/POST]']Wenn man sehr bösartig ist kann man auch immer .intern aufrufen und dann per == vergleichen. Aber nicht wundern wenn das Programm nach längerer Zeit mal 1 GB Speicher braucht ;)
Die Permanent Generation ist relativ klein, da bekommst du schon wesentlich früher Probleme.

HellHorse
2006-06-28, 10:45:18
Monger[/POST]']Mal ne ganz dämliche Frage: wie kann ich denn in Eclipse mir den Byte Code ansehen?
Für jedes Java Problem gibt's ein Eclipse Plugin oder so :D
http://andrei.gmxhome.de/bytecode/index.html

HellHorse
2006-06-28, 11:10:54
Gerade gefunden, hasst die Situation bezüglich interning und Literalen schön zusammen:
http://weblogs.java.net/blog/enicholas/archive/2006/06/all_about_inter.html

Trap
2006-06-28, 15:43:38
Der entsprechende Teil im Java Sprachstandard ist auch recht anschaulich und lesbar.

http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5