Problem bei Mathematikprogramm (Konsolenapplikation)
-
Hallo Leute!
Ich habe eine C++ Konsolenapplikation geschrieben, die ganzrationale Analysis 'kann' und letztendlich eine komplette Kurvendiskussion ausgibt. Das ist auch eigentlich alles kein Problem, aber die newtonsche Näherung funktioniert in meiner aktuellen Version nicht, d.h. float funktion::newton(float) gibt keinen richtigen Wert zurück. (stürzt entweder ab oder gibt 1.#QNAN (also not a number) zurück)
Allerdings habe ich noch eine alte Version, in der es funktioniert, nur ich kann einfach nicht herausfinden, wo der Fehler liegt, ich habe eigentlich haargenau die selben Funktionen in beiden Versionen.
Jedenfalls werde ich die beiden Versionen jetzt posten:
btw: die neue Version enthält auch eine Funktion zur Darstellung von Graphen in ASCII und Ausgabe von Zahlen (auch mit Komma) in Form von ausgeschriebenen Worten.Und: der code mag lang sein, aber die meisten funktionen werden garnicht benutzt!
Also hier die alte Version:
#include <cstdlib> #include <iostream> #include <math.h> using namespace std; class funktion { private: int grad; float* x; public: funktion(); funktion(int g) { grad = g; x = new float[grad + 1]; } void give(int index, float wert) { *(x + index) = wert; } ~funktion() { delete x; } void spell(float zahl) const { spell (zahl, 2); } void spell(float, int) const; void spell_int(float) const; float* f_von_x(); void newtoneingabe() { newtoneingabe(f_von_x()); } void newtoneingabe(float*); void show_term() { show_term(f_von_x()); } void show_term(float*); void show_term(bool b) { show_term(f_von_x(), b); } void show_term(float*, bool); float f_von(float fl) { f_von(f_von_x(), fl); } float f_von(float*, float); float f_strich_von(float fl) { f_strich_von(f_von_x(), fl); } float f_strich_von(float*, float); float approx(float fl) { approx(f_von_x(), fl); } float approx(float*, float); float newton(float fl) { newton(f_von_x(), fl); } float newton(float*, float); void PQ_out() { PQ_out(f_von_x()); } void PQ_out(float*); float* PQ() { PQ(f_von_x()); } // s.u. float* PQ(float*); // <- float* (das 1.) ist hier keine funktion float* restpolynom(float fl) { restpolynom(f_von_x(), fl); } float* restpolynom(float*, float); float* tangente(float fl) { tangente(f_von_x(), fl); } float* tangente(float*, float); float* ableiten() { ableiten(f_von_x()); } float* ableiten(float*); float* ableiten(int n) { ableiten(f_von_x(), n); } float* ableiten(float*, int); float* nullstellen() { nullstellen(f_von_x()); } // s.u. float* nullstellen(float*); // <- float* (das 1.) ist hier keine funktion float* plus_NS(float*, float); // beide float* keine fnkt. }; int main() { funktion* f = new funktion; f -> newtoneingabe(); cout << endl << endl; system("PAUSE"); return 0; } funktion :: funktion() { cout << "Funktionseingabe" << endl; cout << "grad:\t"; cin >> grad; x = new float[grad + 1]; for (int i = 0; i <= grad; i ++) { cout << "a" << grad - i << ":\t"; cin >> x[i]; } cout << endl; } void funktion :: newtoneingabe(float* f) { bool vomfeinsten; cout << "Newtonsche Naeherung" << endl << " [1] Textausgabe"; cout << endl << " [0] Standartausgabe" << endl << " "; cin >> vomfeinsten; if (vomfeinsten) cout << endl << "f von x ist gleich "; else cout << endl << "f(x) = "; show_term(f_von_x(), vomfeinsten); cout << endl << endl << "x-wert fuer nullstellenapproximation: "; float nullstelle; cin >> nullstelle; if (vomfeinsten) { cout << endl << "die naechste nullstelle zu "; spell(nullstelle); cout << " liegt bei x gleich "; spell(approx(f, nullstelle)); cout << "."; } else { cout << endl << "naechste nullstelle zu " << nullstelle << ": "; cout << approx (f, nullstelle); } cout << endl << endl; } void funktion :: show_term(float* f) { if (*f > 0) { for (int i = 1; i <= *f; i ++) { if (f[i] != 0) { if (i > 1) cout << " "; int exponent = (int)*f - i; if (f[i] != 1 && f[i] != -1) { if (i > 1 && f[i] > 0) cout << "+ " << f[i]; if (i == 1 && f[i] > 0) cout << f[i]; if (f[i] < 0) cout << "- " << -f[i]; } else if (i > 1 && f[i] > 0) cout << "+ "; else if (f[i] < 0) cout << "- "; if (exponent == 0 && f[i] == -1 || exponent == 0 && f[i] == 1) cout << 1; if (exponent > 0) cout << "x"; if (exponent > 1) cout << "^" << exponent; } } } else cout << 0; } void funktion :: show_term(float* f, bool b00l) { if (!b00l) show_term(f); if (b00l) { if (*f > 0) { for (int i = 0; i < *f; i ++) { if (f[i + 1] != 0) { if (i > 0) cout << " "; int exponent = (int)*f - 1 - i; if (f[i + 1] != 1 && f[i + 1] != -1) { if (i > 0 && f[i + 1] > 0) { cout << "plus "; spell(f[i + 1]); cout << " "; } if (i == 0 && f[i + 1] > 0) { spell(f[i + 1]); cout << " "; } if (f[i + 1] < 0) { cout << "minus "; spell(- f[i + 1]); cout << " "; } } else if (f[i + 1] == -1) cout << "minus "; else if (i > 0 && f[i + 1] == 1) cout << "plus "; if (exponent == 0 && f[i + 1] == 1 || exponent == 0 && f[i + 1] == -1) { cout << "eins"; } if (exponent > 0) cout << "x"; if (exponent > 1) { cout << " hoch "; spell(exponent); } } } } else cout << "null"; } } void funktion :: spell(float zahl, int nachkommastellen) const { if (zahl < 0) // falls zahl < 0 { cout << "minus "; zahl *= -1; } zahl *= pow((float)10, nachkommastellen); // erstmal runden zahl = floor(zahl + 0.5); zahl /= pow((float)10, nachkommastellen); int i = 1; float zahl_original = zahl; spell_int((int)zahl); // vorm komma zahl -= (int)zahl; if (zahl != 0) cout << "-komma"; // das komma while (i <= nachkommastellen && zahl != 0) // nachm komma { if (zahl != 0) { zahl *= 10; cout << "-"; spell_int((int)zahl); zahl -= (int)zahl; } i ++; } } void funktion :: spell_int(float zahl) const { switch ((int)zahl) // 0-12; 17; 20; 30; 40; 50; 60; 70; 80; 90; 100; { // 1.000; 1337; 1000000; 71349315; 1000000000; case 0: cout << "null"; break; case 1: cout << "eins"; break; case 2: cout << "zwei"; break; case 3: cout << "drei"; break; case 4: cout << "vier"; break; case 5: cout << "fuenf"; break; case 6: cout << "sechs"; break; case 7: cout << "sieben"; break; case 8: cout << "acht"; break; case 9: cout << "neun"; break; case 10: cout << "zehn"; break; case 11: cout << "elf"; break; case 12: cout << "zwoelf"; break; case 17: cout << "siebzehn"; break; // wäre sonst siebENzehn case 20: cout << "zwanzig"; break; // ¯¯ case 30: cout << "dreissig"; break; case 40: cout << "vierzig"; break; case 50: cout << "fuenfzig"; break; case 60: cout << "sechszig"; break; case 70: cout << "siebzig"; break; case 80: cout << "achtzig"; break; case 90: cout << "neunzig"; break; case 100: cout << "hundert"; break; case 1000: cout << "tausend"; break; case 1000000: cout << "eine million"; break; case (int)1e9: cout << "eine milliarde"; break; default: if (zahl > 12 && zahl < 20) // 13-19 { spell_int(zahl - 10); spell_int(10); } for (int i = 20; i <= 90; i += 10) // 21-99 { if (zahl > i && zahl < i + 10) { if (zahl - i != 1) spell_int(zahl - i); else cout << "ein"; cout << "und"; spell_int(i); } } if (zahl > 100 && zahl < 1000) // 101-999 { if ((zahl-(int)zahl%100)/100 != 1) spell_int((zahl-(int)zahl%100)/100); else cout << "ein"; cout << "hundert"; if ((int)zahl % 100 != 0) spell_int((int)zahl % 100); } if (zahl > 1000 && zahl < 1000000) // 1001-999999 { if ((zahl-(int)zahl%1000)/1000!=1) spell_int((zahl-(int)zahl%1000)/1000); else cout << "ein"; cout << "tausend"; if ((int)zahl % 1000 != 0) spell_int((int)zahl % 1000); } if (zahl > 1e6 && zahl < 1e9) // 1000001-999999999 { spell_int((zahl - (int)zahl % (int)1e6) / (int)1e6); cout << "millionen"; if ((int)zahl % (int)1e6 != 0) spell_int((int)zahl % (int)1e6); } if (zahl > 1e9 && zahl < 1e12) // 1000000001-grenze { spell_int((zahl - (int)zahl % (int)1e9) / (int)1e9); cout << "milliarden"; if ((int)zahl % (int)1e9 != 0) spell_int((int)zahl % (int)1e9); } } } float funktion :: f_von(float* f, float x_wert) { float erg = 0; for (int i = 1; i <= *f; i ++) erg += f[i] * pow(x_wert, ((*f - 1) - i + 1)); return erg; } float funktion :: f_strich_von(float* f, float x_wert) { float erg = 0; for (int i = 1; i <= *f - 1; i ++) erg += f[i] * ((*f - 1) - (i - 1)) * pow(x_wert, ((*f - 1) - i)); return erg; } float funktion :: newton(float* f, float x0) { if (f_strich_von(f, x0) != 0) x0 = x0 - f_von(f, x0) / f_strich_von(f, x0); return x0; } float funktion :: approx(float* f, float x0) { float erg = x0; if (f_strich_von(f, erg) == 0) erg += 1e-2; if (x0 - newton(f, x0 + 1e-2) > 0 && x0 - newton(f, x0 - 1e-2) < 0 || x0 - newton(f, x0 + 1e-2) < 0 && x0 - newton(f, x0 - 1e-2) > 0) erg +=1e-2; while (erg != newton(f, erg)) erg = newton(f, erg); return erg; } void funktion :: PQ_out(float* f) { cout << "PQ-Formel" << endl; if (*PQ(f) == 0) cout << "L = { }" << endl << endl; if (*PQ(f) == 2) { if (PQ(f)[1] != PQ(f)[2]) { cout << "N1 ( " << PQ(f)[1] << " | 0 )" << endl; cout << "N2 ( " << PQ(f)[2] << " | 0 )" << endl << endl; } else cout << "N ( " << PQ(f)[1] << " | 0 )\t<- doppelt\n\n"; } } float* funktion :: PQ(float* f) { int nullstellen = 0; float* erg; if (*f == 3) { float temp_x[2] = {f[2] / f[1], f[3] / f[1]}; if (pow((float)pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5) >= 0) { nullstellen += 2; erg = new float[nullstellen + 1]; *erg = nullstellen; *(erg + 1) = - temp_x[0] / 2 - pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5); *(erg + 2) = - temp_x[0] / 2 + pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5); } else { erg = new float[nullstellen + 1]; *erg = 0; } } else { erg = new float[nullstellen + 1]; *erg = 0; } return erg; } float* funktion :: f_von_x() { float* f = new float[grad + 2]; *f = grad + 1; for (int i = 1; i <= grad + 1; i ++) f[i] = x[i - 1]; return f; } float* funktion :: restpolynom(float* vorher, float nullstelle) { float* nachher = new float[(int)*vorher]; *nachher = *vorher - 1; nachher[1] = vorher[1]; for (int i = 2; i <= *vorher - 1 ; i ++) { nachher[i] = nullstelle * nachher[i - 1] + vorher[i]; } return nachher; } float* funktion :: tangente(float* f, float TS) { float* p; if (f_strich_von(f, TS) == 0) { p = new float[2]; p[0] = 1; p[1] = f_von(f, TS); } else { p = new float[3]; p[0] = 2; p[1] = f_strich_von(f, TS); p[2] = -f_strich_von(f, TS) * TS + f_von(f, TS); } return p; } float* funktion :: ableiten(float* f) { float* f_strich; if (*f > 0) { f_strich = new float[(int)*f]; *f_strich = *f - 1; for (int i = 1; i <= *f; i ++) f_strich[i] = f[i] * (*f - i); } else f_strich = f; return f_strich; } float* funktion :: ableiten(float* f, int n) { for (int i = 0; i < n; i ++) f = ableiten(f); return f; } float* funktion :: nullstellen(float* f) { float* NS = new float; *NS = 0; while(*f != 3) { // rausfinden ob überhaupt nullstelle am start !!! NS = plus_NS(NS, approx(0)); f = restpolynom(f, approx(0)); } for (int i = 1; i <= *PQ(f); i ++) NS = plus_NS(NS, PQ(f)[i]); return NS; } float* funktion :: plus_NS(float* list, float NS) { float new_list[(int)*list + 2]; *new_list = *list + 1; for (int i = 1; i <= *list; i ++) new_list[i] = list[i]; new_list[(int)*new_list] = NS; list = new_list; // bubble sort: float temp; for (int i = (int)*list; i > 1; i --) if (list[i] < list[i - 1]) { temp = list[i]; list[i] = list[i - 1]; list[i - 1] = temp; } return list; }Und hier die neue Version:
#include <cstdlib> #include <iostream> #include <math.h> using namespace std; class funktion { private: int grad; float* x; public: funktion(); funktion(int g) { grad = g; x = new float[grad + 1]; } void give(int index, float wert) { *(x + index) = wert; } ~funktion() { delete x; } void spell(float) const; void spell(float, int) const; void spell_int(float) const; float* f_von_x(); void newtoneingabe() { newtoneingabe(f_von_x()); } void newtoneingabe(float*); void show_term() { show_term(f_von_x()); } void show_term(float*); void show_term(bool b) { show_term(f_von_x(), b); } void show_term(float*, bool); float f_von(float fl) { f_von(f_von_x(), fl); } float f_von(float*, float); float f_strich_von(float fl) { f_strich_von(f_von_x(), fl); } float f_strich_von(float* f, float fl) { return f_von(ableiten(f), fl); } float approx(float fl) { approx(f_von_x(), fl); } float approx(float*, float); float newton(float fl) { newton(f_von_x(), fl); } float newton(float*, float); void PQ_out() { PQ_out(f_von_x()); } void PQ_out(float*); float* PQ() { PQ(f_von_x()); } // s.u. float* PQ(float*); // <- float* (das 1.) ist hier keine funktion float* restpolynom(float fl) { restpolynom(f_von_x(), fl); } float* restpolynom(float*, float); float* tangente(float fl) { tangente(f_von_x(), fl); } float* tangente(float*, float); float* ableiten() { ableiten(f_von_x()); } float* ableiten(float*); float* ableiten(int n) { ableiten(f_von_x(), n); } float* ableiten(float*, int); float* nullstellen() { nullstellen(f_von_x()); } // s.u. float* nullstellen(float*); // <- float* (das 1.) ist hier keine funktion float* plus_NS(float*, float); // beide float* keine fnkt. void show_NS() { show_NS(f_von_x()); } void show_NS(float*); // s.o. void draw(float*, float, float, float, float); void draw(float*, float*, float, float, float, float); void draw(float x1, float x2, float y1, float y2) { draw(f_von_x(), x1, x2, y1, y2); } void draw(float* f, float x2, float y2) { draw(f, 0, x2, 0, y2); } void draw(float x2, float y2) { draw(f_von_x(), 0, x2, 0, y2); } void draw(float* f) { draw(f, -5, 5, -5, 5); } void draw() { draw(f_von_x(), -5, 5, -5, 5); } }; int main() { while (true) { funktion* f = new funktion; cout << endl << "f(x) = "; f -> show_term(); //f -> draw(x1, x2, y1, y2); cout << endl << "-5: " << f -> newton(-5) << endl << "5: " << f -> newton(5); // <- AB delete f; cout << endl; } system("PAUSE"); return 0; } funktion :: funktion() { cout << "Funktionseingabe" << endl; cout << "grad:\t"; cin >> grad; x = new float[grad + 1]; for (int i = 0; i <= grad; i ++) { cout << "a" << grad - i << ":\t"; cin >> x[i]; } } void funktion :: newtoneingabe(float* f) { bool vomfeinsten; cout << "Newtonsche Naeherung" << endl << " [1] Textausgabe"; cout << endl << " [0] Standartausgabe" << endl << " "; cin >> vomfeinsten; if (vomfeinsten) cout << endl << "f von x ist gleich "; else cout << endl << "f(x) = "; show_term(f_von_x(), vomfeinsten); cout << endl << endl << "x-wert fuer nullstellenapproximation: "; float nullstelle; cin >> nullstelle; if (vomfeinsten) { cout << endl << "die naechste nullstelle zu "; spell(nullstelle); cout << " liegt bei x gleich "; spell(approx(f, nullstelle)); cout << "."; } else { cout << endl << "naechste nullstelle zu " << nullstelle << ": "; cout << approx (f, nullstelle); } cout << endl << endl; } void funktion :: show_term(float* f) { if (*f > 0) { for (int i = 1; i <= *f; i ++) { if (f[i] != 0) { if (i > 1) cout << " "; int exponent = (int)*f - i; if (f[i] != 1 && f[i] != -1) { if (i > 1 && f[i] > 0) cout << "+ " << f[i]; if (i == 1 && f[i] > 0) cout << f[i]; if (f[i] < 0) cout << "- " << -f[i]; } else if (i > 1 && f[i] > 0) cout << "+ "; else if (f[i] < 0) cout << "- "; if (exponent == 0 && f[i] == -1 || exponent == 0 && f[i] == 1) cout << 1; if (exponent > 0) cout << "x"; if (exponent > 1) cout << "^" << exponent; } } } else cout << 0; } void funktion :: show_term(float* f, bool b00l) { if (!b00l) show_term(f); if (b00l) { if (*f > 0) { for (int i = 0; i < *f; i ++) { if (f[i + 1] != 0) { if (i > 0) cout << " "; int exponent = (int)*f - 1 - i; if (f[i + 1] != 1 && f[i + 1] != -1) { if (i > 0 && f[i + 1] > 0) { cout << "plus "; spell(f[i + 1]); cout << " "; } if (i == 0 && f[i + 1] > 0) { spell(f[i + 1]); cout << " "; } if (f[i + 1] < 0) { cout << "minus "; spell(- f[i + 1]); cout << " "; } } else if (f[i + 1] == -1) cout << "minus "; else if (i > 0 && f[i + 1] == 1) cout << "plus "; if (exponent == 0 && f[i + 1] == 1 || exponent == 0 && f[i + 1] == -1) { cout << "eins"; } if (exponent > 0) cout << "x"; if (exponent > 1) { cout << " hoch "; spell(exponent); } } } } else cout << "null"; } } void funktion :: spell(float zahl) const { spell (zahl, 2); } void funktion :: spell(float zahl, int nachkommastellen) const { if (zahl < 0) // falls zahl < 0 { cout << "minus "; zahl *= -1; } zahl *= pow((float)10, nachkommastellen); // erstmal runden zahl = floor(zahl + 0.5); zahl /= pow((float)10, nachkommastellen); int i = 1; float zahl_original = zahl; spell_int((int)zahl); // vorm komma zahl -= (int)zahl; if (zahl != 0) cout << "-komma"; // das komma while (i <= nachkommastellen && zahl != 0) // nachm komma { if (zahl != 0) { zahl *= 10; cout << "-"; spell_int((int)zahl); zahl -= (int)zahl; } i ++; } } void funktion :: spell_int(float zahl) const { switch ((int)zahl) // 0-12; 17; 20; 30; 40; 50; 60; 70; 80; 90; 100; { // 1.000; 1337; 1000000; 71349315; 1000000000; case 0: cout << "null"; break; case 1: cout << "eins"; break; case 2: cout << "zwei"; break; case 3: cout << "drei"; break; case 4: cout << "vier"; break; case 5: cout << "fuenf"; break; case 6: cout << "sechs"; break; case 7: cout << "sieben"; break; case 8: cout << "acht"; break; case 9: cout << "neun"; break; case 10: cout << "zehn"; break; case 11: cout << "elf"; break; case 12: cout << "zwoelf"; break; case 17: cout << "siebzehn"; break; // wäre sonst siebENzehn case 20: cout << "zwanzig"; break; case 30: cout << "dreissig"; break; case 40: cout << "vierzig"; break; case 50: cout << "fuenfzig"; break; case 60: cout << "sechszig"; break; case 70: cout << "siebzig"; break; case 80: cout << "achtzig"; break; case 90: cout << "neunzig"; break; case 100: cout << "hundert"; break; case 1000: cout << "tausend"; break; case 1000000: cout << "eine million"; break; case (int)1e9: cout << "eine milliarde"; break; default: if (zahl > 12 && zahl < 20) // 13-19 { spell_int(zahl - 10); spell_int(10); } for (int i = 20; i <= 90; i += 10) // 21-99 { if (zahl > i && zahl < i + 10) { if (zahl - i != 1) spell_int(zahl - i); else cout << "ein"; cout << "und"; spell_int(i); } } if (zahl > 100 && zahl < 1000) // 101-999 { if ((zahl-(int)zahl%100)/100 != 1) spell_int((zahl-(int)zahl%100)/100); else cout << "ein"; cout << "hundert"; if ((int)zahl % 100 != 0) spell_int((int)zahl % 100); } if (zahl > 1000 && zahl < 1000000) // 1001-999999 { if ((zahl-(int)zahl%1000)/1000!=1) spell_int((zahl-(int)zahl%1000)/1000); else cout << "ein"; cout << "tausend"; if ((int)zahl % 1000 != 0) spell_int((int)zahl % 1000); } if (zahl > 1e6 && zahl < 1e9) // 1000001-999999999 { spell_int((zahl - (int)zahl % (int)1e6) / (int)1e6); cout << "millionen"; if ((int)zahl % (int)1e6 != 0) spell_int((int)zahl % (int)1e6); } if (zahl > 1e9 && zahl < 1e12) // 1000000001-grenze { spell_int((zahl - (int)zahl % (int)1e9) / (int)1e9); cout << "milliarden"; if ((int)zahl % (int)1e9 != 0) spell_int((int)zahl % (int)1e9); } } } float funktion :: f_von(float* f, float x_wert) { float erg = 0; for (int i = 1; i <= *f; i ++) erg += f[i] * pow(x_wert, *f - i); return erg; } float funktion :: newton(float* f, float x0) { if (f_strich_von(f, x0) != 0) x0 = x0 - f_von(f, x0) / f_strich_von(f, x0); return x0; } float funktion :: approx(float* f, float x0) {/* float erg = x0; if (f_strich_von(f, erg) == 0) erg += 1e-2; while (erg != newton(f, erg)) erg = newton(f, erg); return erg; */ float erg = x0; if (f_strich_von(f, erg) == 0) erg += 1e-2; if (x0 - newton(f, x0 + 1e-2) > 0 && x0 - newton(f, x0 - 1e-2) < 0 || x0 - newton(f, x0 + 1e-2) < 0 && x0 - newton(f, x0 - 1e-2) > 0) erg +=1e-2; while (erg != newton(f, erg)) erg = newton(f, erg); return erg; } void funktion :: PQ_out(float* f) { cout << "PQ-Formel" << endl; if (*PQ(f) == 0) cout << "L = { }" << endl << endl; if (*PQ(f) == 2) { if (PQ(f)[1] != PQ(f)[2]) { cout << "N1 ( " << PQ(f)[1] << " | 0 )" << endl; cout << "N2 ( " << PQ(f)[2] << " | 0 )" << endl << endl; } else cout << "N ( " << PQ(f)[1] << " | 0 )\t<- doppelt\n\n"; } } float* funktion :: PQ(float* f) { int nullstellen = 0; float* erg; if (*f == 3) { float temp_x[2] = {f[2] / f[1], f[3] / f[1]}; if (pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5) >= 0) { nullstellen += 2; erg = new float[nullstellen + 1]; *erg = nullstellen; *(erg + 1) = - temp_x[0] / 2 - pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5); *(erg + 2) = - temp_x[0] / 2 + pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5); } else { erg = new float[nullstellen + 1]; *erg = 0; } } else { erg = new float[nullstellen + 1]; *erg = 0; } return erg; } float* funktion :: f_von_x() { float* f = new float[grad + 2]; *f = grad + 1; for (int i = 1; i <= grad + 1; i ++) f[i] = x[i - 1]; return f; } float* funktion :: restpolynom(float* vorher, float nullstelle) { float* nachher = new float[(int)*vorher]; *nachher = *vorher - 1; nachher[1] = vorher[1]; for (int i = 2; i <= *vorher - 1 ; i ++) { nachher[i] = nullstelle * nachher[i - 1] + vorher[i]; } return nachher; } float* funktion :: tangente(float* f, float TS) { float* p; if (f_strich_von(f, TS) == 0) { p = new float[2]; p[0] = 1; p[1] = f_von(f, TS); } else { p = new float[3]; p[0] = 2; p[1] = f_strich_von(f, TS); p[2] = -f_strich_von(f, TS) * TS + f_von(f, TS); } return p; } float* funktion :: ableiten(float* f) { float* f_strich; if (*f > 0) { f_strich = new float[(int)*f]; *f_strich = *f - 1; for (int i = 1; i <= *f; i ++) f_strich[i] = f[i] * (*f - i); } else f_strich = f; return f_strich; } float* funktion :: ableiten(float* f, int n) { for (int i = 0; i < n; i ++) f = ableiten(f); return f; } float* funktion :: nullstellen(float* f) { float* NS = new float; *NS = 0; while(*f > 1) { // rausfinden ob überhaupt nullstelle am start !!! NS = plus_NS(NS, approx(0)); f = restpolynom(f, approx(0)); } return NS; } float* funktion :: plus_NS(float* list, float NS) { float new_list[(int)*list + 2]; *new_list = *list + 1; for (int i = 1; i <= *list; i ++) new_list[i] = list[i]; new_list[(int)*new_list] = NS; list = new_list; // bubble sort: float temp; for (int i = (int)*list; i > 1; i --) if (list[i] < list[i - 1]) { temp = list[i]; list[i] = list[i - 1]; list[i - 1] = temp; } return list; } void funktion :: show_NS(float* f) { float* NS = nullstellen(f); for (int i = 0; i < *NS; i++) { cout << "N" << i + 1 << ": " << *(NS + i + 1) << endl; } } void funktion :: draw(float* f, float x1, float x2, float y1, float y2) { int hoehe = 47, breite = 79; char feld[hoehe][breite]; for (int i = 0; i < hoehe; i++) { for (int j = 0; j < breite; j++) { feld[i][j] = ' '; /*fill*/ for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * (i + 1) && y2 - (y2 - y1) / hoehe * i <= 0 && k > approx(x1) && k < approx(x2) || f_von(f, k) > y2 - (y2 - y1) / hoehe * i && y2 - (y2 - y1) / hoehe * (i + 1) > 0 && k > approx(x1) && k < approx(x2)) feld[i][j] = 176; } if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0) feld[i][j] = 179; if (y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 196; if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0 && y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 197; for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * i && f_von(f, k) > y2 - (y2 - y1) / hoehe * (i + 1)) feld[i][j] = 219; } } } for (int i = 0; i < hoehe; i++) { cout << endl; for (int j = 0; j < breite; j++) { cout << feld[i][j]; } } } void funktion :: draw(float* f, float* g, float x1, float x2, float y1, float y2) { int hoehe = 47, breite = 79; char feld[hoehe][breite]; for (int i = 0; i < hoehe; i++) { for (int j = 0; j < breite; j++) { feld[i][j] = ' '; /*fill*/ for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * (i + 1) && f_von(g, k) > y2 - (y2 - y1) / hoehe * i || f_von(f, k) > y2 - (y2 - y1) / hoehe * i && f_von(g, k) <= y2 - (y2 - y1) / hoehe * (i + 1)) feld[i][j] = 176; } if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0) feld[i][j] = 179; if (y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 196; if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0 && y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 197; for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * i && f_von(f, k) > y2 - (y2 - y1) / hoehe * (i + 1) || f_von(g, k) <= y2 - (y2 - y1) / hoehe * i && f_von(g, k) > y2 - (y2 - y1) / hoehe * (i + 1)) feld[i][j] = 219; } } } for (int i = 0; i < hoehe; i++) { cout << endl; for (int j = 0; j < breite; j++) { cout << feld[i][j]; } } }
-
vielleicht solltest du ein paar checks oder exception handler einbauen, um division durch 0 o.ä. abzufangen. ansonsten: lass es im debugger laufen und wenn ein fehler passiert, dann guckste dir den backtrace an...
-
Division durch 0 ist ausgeschlossen
und bei der ersten version funktioniert es ja
-
So hab das Problem gelöst, es lag an der neuen float funktion::f_strich_von(float)...
Naja wer die Funktionen interessant findet kann sie sich ja mal ansehen, aber im moment fehlt noch eine benutzerobverfläche und die funktion, die die kurvendiskussion ausgibt... ich werde auchnoch integralrechnungen implementieren und so zeug, aber however das problem is gelösthauen sie rein!
hier ist der code:
#include <cstdlib> #include <iostream> #include <math.h> using namespace std; class funktion { private: int grad; float* x; public: funktion(); funktion(int g) { grad = g; x = new float[grad + 1]; } void give(int index, float wert) { *(x + index) = wert; } ~funktion() { delete x; } void spell(float) const; void spell(float, int) const; void spell_int(float) const; float* f_von_x(); void newtoneingabe() { newtoneingabe(f_von_x()); } void newtoneingabe(float*); void show_term() { show_term(f_von_x()); } void show_term(float*); void show_term(bool b) { show_term(f_von_x(), b); } void show_term(float*, bool); float f_von(float fl) { f_von(f_von_x(), fl); } float f_von(float*, float); float f_strich_von(float fl) { f_strich_von(f_von_x(), fl); } float f_strich_von(float*, float); float approx(float fl) { approx(f_von_x(), fl); } float approx(float*, float); float newton(float fl) { newton(f_von_x(), fl); } float newton(float*, float); void PQ_out() { PQ_out(f_von_x()); } void PQ_out(float*); float* PQ() { PQ(f_von_x()); } // s.u. float* PQ(float*); // <- float* (das 1.) ist hier keine funktion float* restpolynom(float fl) { restpolynom(f_von_x(), fl); } float* restpolynom(float*, float); float* tangente(float fl) { tangente(f_von_x(), fl); } float* tangente(float*, float); float* ableiten() { ableiten(f_von_x()); } float* ableiten(float*); float* ableiten(int n) { ableiten(f_von_x(), n); } float* ableiten(float*, int); float* nullstellen() { nullstellen(f_von_x()); } // s.u. float* nullstellen(float*); // <- float* (das 1.) ist hier keine funktion float* plus_NS(float*, float); // beide float* keine fnkt. void show_NS() { show_NS(f_von_x()); } void show_NS(float*); // s.o. void draw(float*, float, float, float, float); void draw(float*, float*, float, float, float, float); void draw(float x1, float x2, float y1, float y2) { draw(f_von_x(), x1, x2, y1, y2); } void draw(float* f, float x2, float y2) { draw(f, 0, x2, 0, y2); } void draw(float x2, float y2) { draw(f_von_x(), 0, x2, 0, y2); } void draw(float* f) { draw(f, -5, 5, -5, 5); } void draw() { draw(f_von_x(), -5, 5, -5, 5); } }; int main() { while (true) { funktion* f = new funktion; cout << endl << "f(x) = "; f -> show_term(); //f -> draw(x1, x2, y1, y2); f -> newtoneingabe(); delete f; cout << endl; } system("PAUSE"); return 0; } funktion :: funktion() { cout << "Funktionseingabe" << endl; cout << "grad:\t"; cin >> grad; x = new float[grad + 1]; for (int i = 0; i <= grad; i ++) { cout << "a" << grad - i << ":\t"; cin >> x[i]; } } void funktion :: newtoneingabe(float* f) { bool vomfeinsten; cout << "Newtonsche Naeherung" << endl << " [1] Textausgabe"; cout << endl << " [0] Standartausgabe" << endl << " "; cin >> vomfeinsten; if (vomfeinsten) cout << endl << "f von x ist gleich "; else cout << endl << "f(x) = "; show_term(f_von_x(), vomfeinsten); cout << endl << endl << "x-wert fuer nullstellenapproximation: "; float nullstelle; cin >> nullstelle; if (vomfeinsten) { cout << endl << "die naechste nullstelle zu "; spell(nullstelle); cout << " liegt bei x gleich "; spell(approx(f, nullstelle)); cout << "."; } else { cout << endl << "naechste nullstelle zu " << nullstelle << ": "; cout << approx (f, nullstelle); } cout << endl << endl; } void funktion :: show_term(float* f) { if (*f > 0) { for (int i = 1; i <= *f; i ++) { if (f[i] != 0) { if (i > 1) cout << " "; int exponent = (int)*f - i; if (f[i] != 1 && f[i] != -1) { if (i > 1 && f[i] > 0) cout << "+ " << f[i]; if (i == 1 && f[i] > 0) cout << f[i]; if (f[i] < 0) cout << "- " << -f[i]; } else if (i > 1 && f[i] > 0) cout << "+ "; else if (f[i] < 0) cout << "- "; if (exponent == 0 && f[i] == -1 || exponent == 0 && f[i] == 1) cout << 1; if (exponent > 0) cout << "x"; if (exponent > 1) cout << "^" << exponent; } } } else cout << 0; } void funktion :: show_term(float* f, bool b00l) { if (!b00l) show_term(f); if (b00l) { if (*f > 0) { for (int i = 0; i < *f; i ++) { if (f[i + 1] != 0) { if (i > 0) cout << " "; int exponent = (int)*f - 1 - i; if (f[i + 1] != 1 && f[i + 1] != -1) { if (i > 0 && f[i + 1] > 0) { cout << "plus "; spell(f[i + 1]); cout << " "; } if (i == 0 && f[i + 1] > 0) { spell(f[i + 1]); cout << " "; } if (f[i + 1] < 0) { cout << "minus "; spell(- f[i + 1]); cout << " "; } } else if (f[i + 1] == -1) cout << "minus "; else if (i > 0 && f[i + 1] == 1) cout << "plus "; if (exponent == 0 && f[i + 1] == 1 || exponent == 0 && f[i + 1] == -1) { cout << "eins"; } if (exponent > 0) cout << "x"; if (exponent > 1) { cout << " hoch "; spell(exponent); } } } } else cout << "null"; } } void funktion :: spell(float zahl) const { spell (zahl, 2); } void funktion :: spell(float zahl, int nachkommastellen) const { if (zahl < 0) // falls zahl < 0 { cout << "minus "; zahl *= -1; } zahl *= pow((float)10, nachkommastellen); // erstmal runden zahl = floor(zahl + 0.5); zahl /= pow((float)10, nachkommastellen); int i = 1; float zahl_original = zahl; spell_int((int)zahl); // vorm komma zahl -= (int)zahl; if (zahl != 0) cout << "-komma"; // das komma while (i <= nachkommastellen && zahl != 0) // nachm komma { if (zahl != 0) { zahl *= 10; cout << "-"; spell_int((int)zahl); zahl -= (int)zahl; } i ++; } } void funktion :: spell_int(float zahl) const { switch ((int)zahl) // 0-12; 17; 20; 30; 40; 50; 60; 70; 80; 90; 100; { // 1.000; 1337; 1000000; 71349315; 1000000000; case 0: cout << "null"; break; case 1: cout << "eins"; break; case 2: cout << "zwei"; break; case 3: cout << "drei"; break; case 4: cout << "vier"; break; case 5: cout << "fuenf"; break; case 6: cout << "sechs"; break; case 7: cout << "sieben"; break; case 8: cout << "acht"; break; case 9: cout << "neun"; break; case 10: cout << "zehn"; break; case 11: cout << "elf"; break; case 12: cout << "zwoelf"; break; case 17: cout << "siebzehn"; break; // wäre sonst siebENzehn case 20: cout << "zwanzig"; break; case 30: cout << "dreissig"; break; case 40: cout << "vierzig"; break; case 50: cout << "fuenfzig"; break; case 60: cout << "sechszig"; break; case 70: cout << "siebzig"; break; case 80: cout << "achtzig"; break; case 90: cout << "neunzig"; break; case 100: cout << "hundert"; break; case 1000: cout << "tausend"; break; case 1000000: cout << "eine million"; break; case (int)1e9: cout << "eine milliarde"; break; default: if (zahl > 12 && zahl < 20) // 13-19 { spell_int(zahl - 10); spell_int(10); } for (int i = 20; i <= 90; i += 10) // 21-99 { if (zahl > i && zahl < i + 10) { if (zahl - i != 1) spell_int(zahl - i); else cout << "ein"; cout << "und"; spell_int(i); } } if (zahl > 100 && zahl < 1000) // 101-999 { if ((zahl-(int)zahl%100)/100 != 1) spell_int((zahl-(int)zahl%100)/100); else cout << "ein"; cout << "hundert"; if ((int)zahl % 100 != 0) spell_int((int)zahl % 100); } if (zahl > 1000 && zahl < 1000000) // 1001-999999 { if ((zahl-(int)zahl%1000)/1000!=1) spell_int((zahl-(int)zahl%1000)/1000); else cout << "ein"; cout << "tausend"; if ((int)zahl % 1000 != 0) spell_int((int)zahl % 1000); } if (zahl > 1e6 && zahl < 1e9) // 1000001-999999999 { spell_int((zahl - (int)zahl % (int)1e6) / (int)1e6); cout << "millionen"; if ((int)zahl % (int)1e6 != 0) spell_int((int)zahl % (int)1e6); } if (zahl > 1e9 && zahl < 1e12) // 1000000001-grenze { spell_int((zahl - (int)zahl % (int)1e9) / (int)1e9); cout << "milliarden"; if ((int)zahl % (int)1e9 != 0) spell_int((int)zahl % (int)1e9); } } } float funktion :: f_von(float* f, float x_wert) { float erg = 0; for (int i = 1; i <= *f; i ++) erg += f[i] * pow(x_wert, ((*f - 1) - i + 1)); return erg; } float funktion :: f_strich_von(float* f, float x_wert) { float erg = 0; for (int i = 1; i <= *f - 1; i ++) erg += f[i] * ((*f - 1) - (i - 1)) * pow(x_wert, ((*f - 1) - i)); return erg; } float funktion :: newton(float* f, float x0) { if (f_strich_von(f, x0) != 0) x0 = x0 - f_von(f, x0) / f_strich_von(f, x0); return x0; } float funktion :: approx(float* f, float x0) { float erg = x0; if (f_strich_von(f, erg) == 0) erg += 1e-2; if (x0 - newton(f, x0 + 1e-2) > 0 && x0 - newton(f, x0 - 1e-2) < 0 || x0 - newton(f, x0 + 1e-2) < 0 && x0 - newton(f, x0 - 1e-2) > 0) erg +=1e-2; while (erg != newton(f, erg)) erg = newton(f, erg); return erg; } void funktion :: PQ_out(float* f) { cout << "PQ-Formel" << endl; if (*PQ(f) == 0) cout << "L = { }" << endl << endl; if (*PQ(f) == 2) { if (PQ(f)[1] != PQ(f)[2]) { cout << "N1 ( " << PQ(f)[1] << " | 0 )" << endl; cout << "N2 ( " << PQ(f)[2] << " | 0 )" << endl << endl; } else cout << "N ( " << PQ(f)[1] << " | 0 )\t<- doppelt\n\n"; } } float* funktion :: PQ(float* f) { int nullstellen = 0; float* erg; if (*f == 3) { float temp_x[2] = {f[2] / f[1], f[3] / f[1]}; if (pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5) >= 0) { nullstellen += 2; erg = new float[nullstellen + 1]; *erg = nullstellen; *(erg + 1) = - temp_x[0] / 2 - pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5); *(erg + 2) = - temp_x[0] / 2 + pow(pow(temp_x[0] / 2, 2) - temp_x[1], (float)0.5); } else { erg = new float[nullstellen + 1]; *erg = 0; } } else { erg = new float[nullstellen + 1]; *erg = 0; } return erg; } float* funktion :: f_von_x() { float* f = new float[grad + 2]; *f = grad + 1; for (int i = 1; i <= grad + 1; i ++) f[i] = x[i - 1]; return f; } float* funktion :: restpolynom(float* vorher, float nullstelle) { float* nachher = new float[(int)*vorher]; *nachher = *vorher - 1; nachher[1] = vorher[1]; for (int i = 2; i <= *vorher - 1 ; i ++) { nachher[i] = nullstelle * nachher[i - 1] + vorher[i]; } return nachher; } float* funktion :: tangente(float* f, float TS) { float* p; if (f_strich_von(f, TS) == 0) { p = new float[2]; p[0] = 1; p[1] = f_von(f, TS); } else { p = new float[3]; p[0] = 2; p[1] = f_strich_von(f, TS); p[2] = -f_strich_von(f, TS) * TS + f_von(f, TS); } return p; } float* funktion :: ableiten(float* f) { float* f_strich; if (*f > 0) { f_strich = new float[(int)*f]; *f_strich = *f - 1; for (int i = 1; i <= *f; i ++) f_strich[i] = f[i] * (*f - i); } else f_strich = f; return f_strich; } float* funktion :: ableiten(float* f, int n) { for (int i = 0; i < n; i ++) f = ableiten(f); return f; } float* funktion :: nullstellen(float* f) { float* NS = new float; *NS = 0; while(*f > 1) { // rausfinden ob überhaupt nullstelle am start !!! NS = plus_NS(NS, approx(0)); f = restpolynom(f, approx(0)); } return NS; } float* funktion :: plus_NS(float* list, float NS) { float new_list[(int)*list + 2]; *new_list = *list + 1; for (int i = 1; i <= *list; i ++) new_list[i] = list[i]; new_list[(int)*new_list] = NS; list = new_list; // bubble sort: float temp; for (int i = (int)*list; i > 1; i --) if (list[i] < list[i - 1]) { temp = list[i]; list[i] = list[i - 1]; list[i - 1] = temp; } return list; } void funktion :: show_NS(float* f) { float* NS = nullstellen(f); for (int i = 0; i < *NS; i++) { cout << "N" << i + 1 << ": " << *(NS + i + 1) << endl; } } void funktion :: draw(float* f, float x1, float x2, float y1, float y2) { int hoehe = 47, breite = 79; char feld[hoehe][breite]; for (int i = 0; i < hoehe; i++) { for (int j = 0; j < breite; j++) { feld[i][j] = ' '; /*fill*/ for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * (i + 1) && y2 - (y2 - y1) / hoehe * i <= 0 && k > approx(x1) && k < approx(x2) || f_von(f, k) > y2 - (y2 - y1) / hoehe * i && y2 - (y2 - y1) / hoehe * (i + 1) > 0 && k > approx(x1) && k < approx(x2)) feld[i][j] = 176; } if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0) feld[i][j] = 179; if (y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 196; if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0 && y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 197; for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * i && f_von(f, k) > y2 - (y2 - y1) / hoehe * (i + 1)) feld[i][j] = 219; } } } for (int i = 0; i < hoehe; i++) { cout << endl; for (int j = 0; j < breite; j++) { cout << feld[i][j]; } } } void funktion :: draw(float* f, float* g, float x1, float x2, float y1, float y2) { int hoehe = 47, breite = 79; char feld[hoehe][breite]; for (int i = 0; i < hoehe; i++) { for (int j = 0; j < breite; j++) { feld[i][j] = ' '; /*fill*/ for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * (i + 1) && f_von(g, k) > y2 - (y2 - y1) / hoehe * i || f_von(f, k) > y2 - (y2 - y1) / hoehe * i && f_von(g, k) <= y2 - (y2 - y1) / hoehe * (i + 1)) feld[i][j] = 176; } if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0) feld[i][j] = 179; if (y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 196; if (x1 + (x2 - x1) / breite * j <= 0 && x1 + (x2 - x1) / breite * (j + 1) > 0 && y2 - (y2 - y1) / hoehe * i > 0 && y2 - (y2 - y1) / hoehe * (i + 1) <= 0) feld[i][j] = 197; for (float k = x1 + (x2 - x1) / breite * j; k < x1 + (x2 - x1) / breite * (j + 1); k += (x2 - x1) / breite / 100) { if (f_von(f, k) <= y2 - (y2 - y1) / hoehe * i && f_von(f, k) > y2 - (y2 - y1) / hoehe * (i + 1) || f_von(g, k) <= y2 - (y2 - y1) / hoehe * i && f_von(g, k) > y2 - (y2 - y1) / hoehe * (i + 1)) feld[i][j] = 219; } } } for (int i = 0; i < hoehe; i++) { cout << endl; for (int j = 0; j < breite; j++) { cout << feld[i][j]; } } }