W
floriandarter schrieb:
für die Uni soll ich ein c++ Programm schreiben(mit Visual Studio 2010), mit dem die Nullstellen einer Polynomfunktion berechnet werden können. Der benutzer soll den Grad n des Polynoms eingeben und dann soll ein Array mit n+1 Feldern angelegt werden. Mein Problem ist, dass ich das Array nicht an die Funktion evalPolynom übergeben kann und auch nich weiß, ob die funktion das Polynom auswertet.
Hallo floriandarter,
solche Art Aufgabenstellungen lesen zu müssen, ist ein Trauerspiel. Da wird gefordert, new zu verwenden, anscheinend bevor überhaupt was über std::vector end/oder std::string erzählt wird.
Die Aufgabestellung 'Nullstellen eines Polynoms mit Newton-Verfahren' schreit doch geradezu nach einem Funktionstemplate für das Newtonverfahren und einer Klasse für das Polynom. In unten stehenden Code habe ich das mal skizziert.
Deine Funktion 'evalPolynom' habe ich durch eine operator() ersetzt (Zeile 20-28). Dies hat den Vorteil, dass man ein Objekt der Klasse Polynom wie eine Funktion nutzen kann (siehe Zeile 68 und 70). Weiter benutze ich zur Berechnung des Polynoms das Horner-Schema - ich hoffe für Dich, dass das was Du in 'evalPolynom' codiert hast, nicht an Deiner Uni gelehrt wird.
Die Klasse Polynom hat noch eine Methode 'ableitung', mit der die Ableitung des Polynoms bestimmt und als Returnwert zurück gegeben wird (Zeile 35-44).
Und außerdem habe ich die Methode 'sub' hinzugefügt (Zeile 46-59). Diese reduziert das Polynom um eine Nullstelle, indem es das betreffende Objekt in ein Polynom umwandelt, welches das Ergebnis der Division Polynom/(x - x0) ist. Damit wird sicher gestellt, dass nicht eine Nullstelle mehrfach gefunden wird. Wird eine Nullstelle gefunden, so wird sie mittels 'sub' einfach aus dem Polynom entfernt (Zeile 96).
#include <iostream>
#include <vector>
#include <cassert>
#include <cmath> // std::abs
#include <stdexcept> // std::invalid_argument
#include <memory> // std::unique_ptr
class Polynom
{
public:
Polynom() : m_koeff( 1 ) {}
template< typename I >
Polynom( I von, I bis )
: m_koeff( von, bis )
{
assert( !m_koeff.empty() );
}
double operator()( double x ) const
{
// Berechnung des Funktionwertes an der Stelle 'x' nach dem
// http://de.wikipedia.org/wiki/Horner-Schema
double ergebnis = 0;
for( auto i = m_koeff.rbegin(); i != m_koeff.rend(); ++i )
ergebnis = ergebnis * x + *i;
return ergebnis;
}
int grad() const
{
return int(m_koeff.size()) - 1;
}
Polynom ableitung() const
{
if( grad() <= 0 )
return Polynom();
std::vector< double > koeff;
int faktor = 1;
for( auto i = m_koeff.begin() + 1; i != m_koeff.end(); ++i, ++faktor )
koeff.push_back( faktor * *i );
return Polynom( koeff.begin(), koeff.end() );
}
double sub( double x0 )
{ // -- dividiert das Polynom durch (x - x0) und git den Rest zurück
assert( grad() > 0 );
std::vector< double > koeff;
auto i = m_koeff.rbegin();
double rest = *i++;
for( ; i != m_koeff.rend(); ++i )
{
koeff.push_back( rest );
rest = x0 * rest + *i;
}
m_koeff.assign( koeff.rbegin(), koeff.rend() );
return rest;
}
private:
std::vector< double > m_koeff;
};
template< typename Fkt, typename DFkt >
double newton( Fkt func, DFkt dfunc, double x, double eps )
{
int check = 0;
for( double y; std::abs( y = func( x ) ) > eps; ++check )
{
x -= y / dfunc( x );
if( check > 100 ) // verhindert ggf. die Endlosschleife
{ // Bem.: Exception ist hier vielleich übertrieben ...
throw std::invalid_argument( "Newton Verfahren: x konvertiert nicht" );
}
}
return x;
}
int main()
{
using namespace std;
cout<<"Newton-Verfahren zur Nullstellenbestimmung "<<endl;
int n;
cout << "Grad der Funktion: ";
if( cin >> n && n > 0 ) // nur ein Grad des Polynoms >0 ist zulässig
{
unique_ptr< double[] > koeff( new double[n+1] ); // wenn schon 'new', dann mit smart-Pointer
int i = 0;
for( double a_i; i <= n && (cout<<"\nBitte geben sie a" << i << " ein: ", cin >> a_i); ++i )
koeff[i] = a_i;
if( cin ) // Eingabe war ok?
{
try
{
Polynom f( koeff.get(), koeff.get()+n+1 );
for( double x0; f.grad() > 0; f.sub( x0 ) )
cout << "\nNullstelle: " << (x0 = newton( f, f.ableitung(), 0.0, 1.E-8 )) << endl;
}
catch( const std::exception& ex )
{
cerr << "\n### Exception: " << ex.what() << endl;
}
}
}
return 0;
}
.. an welcher Uni studierst Du, und was genau?
Gruß
Werner