Polynomdivision, weiß nich was ich falschmache
-
Das ist etwa so wie mit dem Bruch 1/3. In dezimaler Schreibweise ist der 0.33333..., aber wir koennen ihn nicht mit unendlich vielen Nachkommastellen aufschreiben und brechen z.B. nach der 5-ten Stelle ab. Jetzt ist natuerlich 1/3 + 1/3 + 1/3 gleich 1, aber 0.33333 + 0.33333 + 0.33333 ist eben nicht exakt 1. Das gleiche passiert dem Computer. Intern werden Zahlen im Binaerformat dargestellt. 0.1 (oder 0.01 oder 0.001 oder ...) sind nicht exakt darstellbar, genauso wie 1/3 im Dezimalsystem. Dadurch ergeben sich Ungenauigkeiten beim Addieren und die exakte Loesung wird nicht getroffen.
-
achso das is dann im binarsystem keine exakte Zahl
-
knivil schrieb:
Über IR ist jedes Polynom vom Grade 3 oder höher faktorisierbar.
Ich nehme mal an, dass mit IR die komplexen Zahlen gemeint sind. Aber ich sehe in dem Codefragment keine komplexen Zahlen.
Er meint sicherlich die reellen Zahlen.
[Edit] War Müll.
-
knivil schrieb:
Über IR ist jedes Polynom vom Grade 3 oder höher faktorisierbar.
Ich nehme mal an, dass mit IR die komplexen Zahlen gemeint sind.
Du hast mit Mathematik nicht so viel am Hut, oder? IR steht für den Körper der reellen Zahlen.
Vermutlich, weil sie ziemlich umständlich ist.
Die Loesungsformeln sind schon so einfach wie moeglich.
Aber vielleicht nicht einfach genug.
-
Bashar schrieb:
Du hast mit Mathematik nicht so viel am Hut, oder?
Doch schon, aber du hast geschrieben:
Grade 3 oder höher
Und ich ueberlege mir ein Polynom 4-ten Grades, das nicht faktorisierbar ist ...
Ich habe komplexe Zahlen nur vermutet, weil es bestimmt ein Polynom 4-ten Grades gibt, dass keine reeelen Nullstellen hat.
-
Gibt es denn im binarsystem eine exakte Zahl, die kleiner als eins ist und duch multiplikation zu eins ergänzt werden kann?
-
2 und alle Potenzen (...-2,1,0,1,2 ...).
-
also geht mein Ansatz nur für ganze Zahlen, weil bei dem Computer z.b. 0.1*10 nicht exakt 1 ist?
-
knivil schrieb:
Und ich ueberlege mir ein Polynom 4-ten Grades, das nicht faktorisierbar ist ...
Ja, x^4 + x^2 + 1 ist nicht in Linearfaktoren zerlegbar, gähn. Das hab ich aber auch nicht behauptet, also spar dir deine Energie und schlag lieber den Satz nach, der besagt, dass irreduzible Polynome über IR den Höchstgrad 2 haben.
-
also geht mein Ansatz nur für ganze Zahlen, weil bei dem Computer z.b. 0.1*10 nicht exakt 1 ist?
aber dann müsste doch folgendes funktionieren:if( aa*pol*pol*pol + bb*pol*pol + cc*pol + dd > -0.01 && aa*pol*pol*pol + bb*pol*pol + cc*pol + dd< 0.01)
leider funktioniet das auch nicht.
Das kann auch nicht daran liegen, dass die Abweichung höher als 0.01 ist weil das folgende funktioniert auch nicht:if( aa*pol*pol*pol + bb*pol*pol + cc*pol + dd > -1 && aa*pol*pol*pol + bb*pol*pol + cc*pol + dd< 1)
zudem habe ich auch mal folgendes eingefügt:
pol = loop_pol; cout << " " << pol; if( aa*pol*pol*pol + bb*pol*pol + cc*pol + dd > -1 && aa*pol*pol*pol + bb*pol*pol + cc*pol + dd< 1)
in der Ausgabe werden dann aber auch ganze Zahlen angezeigt. Somit müssten auch ganze Zahlen als nullstellen erkannt werden.
Ist das jetzt doch nen andreres problen?
-
Bashar schrieb:
irreduzible Polynome über IR den Höchstgrad 2 haben.
Ok, hab es nachgelesen.
@Uederli: Habe grad keinen Compiler zur Hand um zu Testen.
-
also ich habs ja getestet und es funktioniert, wie beschrieben, leider nicht.
dann kann es ja eigentlich nicht an diesen Ungenauigkeiten im Dualsystem liegen
-
Ich habe das jetzt folgendermaßen umfgeformt:
double pol = -1000.0; double addpol = 0.1; for ( double loop_pol = -1005; loop_pol < 1000; loop_pol += 0.1) { pol += addpol; cout << " " << pol; if( aa*pol*pol*pol + bb*pol*pol + cc*pol + dd > -1 && aa*pol*pol*pol + bb*pol*pol + cc*pol + dd< 1) { x1 = pol; double p = (bb+x1*aa)/aa; double q = (cc+x1*bb+x1*x1*aa)/aa; x2 = -(p/2)+ sqrt(((p*p)/4)-q); x3 = -(p/2)- sqrt(((p*p)/4)-q); cout << "\n x1 = " << x1; cout << "\n x2 = " << x2; cout << "\n x3 = " << x3; getch(); break; } }
demnach müsste es bei einer Abweichung auch klappen, aber es funktioniert trotzdem nicht.
Die Zeile
cout << " " << pol;
gibt dann ja aus, was pol gerade ist. Und da werden immer die exaten Zahlen angezeigt, also keine Abweichung.
Hat einer eine Idee warum es immernochnicht klappt?
-
double pol = -1000.0; double addpol = 0.01; for ( double loop_pol = -1005; loop_pol < 1000; loop_pol += 0.01) { pol += addpol; if( aa*pol*pol*pol + bb*pol*pol + cc*pol + dd > -0.1 && aa*pol*pol*pol + bb*pol*pol + cc*pol + dd< 0.1) { x1 = pol; double p = (bb+x1*aa)/aa; double q = (cc+x1*bb+x1*x1*aa)/aa; x2 = -(p/2)+ sqrt(((p*p)/4)-q); x3 = -(p/2)- sqrt(((p*p)/4)-q); cout << "\n x1 = " << x1; cout << "\n x2 = " << x2; cout << "\n x3 = " << x3; getch(); break; } }
Es klappt!!!
Vielen Dank für eure Hilfe!!
Es war letzten endes also doch die Abweichung, die entsteht, wenn man 0,1 addiert
-
Das ist trotzdem numerisch noch sehr ungeschickt.
Alternativvorschlag: Teste, ob ein Vorzeichenwechsel stattfindet. Wenn Du also in kleinen Schritten "von links nach rechts" läufst und einen solchen Vorzeichenwechsel entdeckst, kannst Du dieses Intervall, was durch die zwei letzten Stellen gegeben ist die Nullstelle enthalten muss und, gesondert betrachten (zB mit dem Sekantenverfahren).
-
Ich versehe jetzt nicht ganz was du meinst.
Teste, ob ein Vorzeichenwechsel stattfindet.
ich dachte das mache ich mit:
if( aa*pol*pol*pol + bb*pol*pol + cc*pol + dd > -0.00001 && aa*pol*pol*pol + bb*pol*pol + cc*pol + dd< 0.00001)
was meinst du mit:
gesondert betrachten
?
-
Dein Problem ist, dass dein Verfahren zu ungenau ist. Wenn du in 0.01-er Schritten suchst, kriegst du eben auch keine besser Genauigkeit als 0.01. Es gibt aber Verfahren, mit denen man beliebig exakte Näherungen von Nullstellen erhalten kann, darunter ist z.B. das Sekantenverfahren.
-
Uederli schrieb:
Ich versehe jetzt nicht ganz was du meinst.
Teste, ob ein Vorzeichenwechsel stattfindet.
ich dachte das mache ich mit:
if( aa*pol*pol*pol + bb*pol*pol + cc*pol + dd > -0.00001 && aa*pol*pol*pol + bb*pol*pol + cc*pol + dd< 0.00001)
Nee nee nee, ich dachte da eher an so etwas wie
#include <iostream> struct poly3 { double a,b,c,d; explicit poly3(double a=0, double b=0, double c=0, double d=0) : a(a),b(b),c(c),d(d) {} double operator()(double x) const { return d+x*(c+x*(b+x*a)); } }; poly3 ableiten(poly3 const& p) { return poly3(0, 3*p.a, 2*p.b, p.c); } double newton(poly3 const& p, double x, int wieoft) { poly3 const d = ableiten(p); for (int k=0; k<wieoft; ++k) { double y = p(x); double m = d(x); x -= y/m; } return x; } int main() { poly3 p (1.00, 1.72, -6.36, -7.20); double oldx = 0; double oldy = 0; for (int i=-100; i<=100; ++i) { double x = i * 0.1; double y = p(x); if (i>-100) { if (y*oldy<=0) { // Irgendwo zwischen oldx und x muss eine Nullstelle sein // Initiale Schaetzung durch Sekante: double n = oldx + -oldy/(y-oldy)*(x-oldx); n = newton(p,n,5); std::cout << "Nullstelle bei x=" << n << ", p(x)=" << p(n) << '\n'; } } oldx = x; oldy = y; } }
-
nix
-