Funktionsuntersuchung

Dieses Programm dient dazu, Funktionsuntersuchungen von Funktionen zu machen.

function.cpp

/*
 * Function - a program to calculate with polynomial functions
 * Copyright (C) 2005 Nicolas Bellm
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * g++ function.cpp
 *
 */

#include <iostream>
#include <sstream>
#include <math.h>
#include "function.h"

double Function::f(double x)
{
  double ret = k[0];

  for (int i = 1; i < k.size(); i++)
    ret = ret * x + k[i];

  return ret;
}

Function* Function::derive()
{
  vector<double> ret( degree() );

  for (int i = 0; i < ret.size(); i++)
    ret[i] = k[i] * ( degree() - i );

  string name = m_name + "'";

  return new Function( name, ret );
}

Function* Function::derive(int i)
{
  Function *f = this;
  
  for (int j=0; j<i; j++)
    f = f->derive();

  return f;
}

list<double> Function::roots()
{
  list<double> ret;
  double d, p, q;

  switch ( degree() )
  {
    case 0:
      if ( k[0] == 0 )
	ret.push_back( 0 );
      break;

    case 1:
      ret.push_back( -k[1] / k[0] );
      break;

    case 2:
      d = k[1] * k[1] - 4 * k[0] * k[2];

      if ( d > 0 )
      {
        ret.push_back( ( -k[1] + sqrt( d ) ) / ( 2 * k[0] ) );
	ret.push_back( ( -k[1] - sqrt( d ) ) / ( 2 * k[0] ) );
      }
      else if ( d == 0 )
      {
        ret.push_back( -k[1] / ( 2 * k[0] ) );
      }
      break;

    case 3:
      p = k[2]/k[0]-(k[1]*k[1])/(3*k[0]*k[0]);
      q = k[3]/k[0]+(2*k[1]*k[1]*k[1])/(27*k[0]*k[0]*k[0])-(k[1]*k[2])/(3*k[0]*k[0]);
      d = (q*q)/4+(p*p*p)/27;

      if ( d > 0 )
	ret.push_back( cbrt(-q/2+sqrt(q*q/4+p*p*p/27))+
		       cbrt(-q/2-sqrt(q*q/4+p*p*p/27))-k[1]/3*k[0] );
      else if ( d == 0 ) // Rundungsfehler ?
      {
	ret.push_back( cbrt(q/2)-k[1]/(3*k[0]) );
	ret.push_back( -cbrt(4*q)-k[1]/(3*k[0]) );
      }
      else
      {
	ret.push_back( 2*sqrt(-p/3)*cos(1/3.*acos(-q/2*sqrt(-27/(p*p*p))))-k[1]/(3*k[0]) );
	ret.push_back( -2*sqrt(-p/3)*cos(1/3.*acos(-q/2*sqrt(-27/(p*p*p)))+M_PIl/3)-k[1]/(3*k[0]) );
	ret.push_back( -2*sqrt(-p/3)*cos(1/3.*acos(-q/2*sqrt(-27/(p*p*p)))-M_PIl/3)-k[1]/(3*k[0]) );
      }
      break;
  }

  return ret;
}

list<Point> Function::extrema()
{
  list<double> roots = derive()->roots();
  list<Point> ret;

  for (list<double>::iterator it = roots.begin(); it != roots.end(); it++)
  {
    Point p(*it,f(*it));
    ret.push_back(p);
  }
  return ret;
}

string Function::toString()
{
  ostringstream ret;
  ret << m_name << "(x) = ";

  int i;
  for (i = 0; i < k.size(); i++)
  {
    if ( k[i] != 0 )
    {
      if ( k[i] > 0 )
      {
	if ( i != 0 )
	  ret << "+ ";
      }
      else
	ret << "- ";

      if ( fabs( k[i] ) != 1 || degree() - i == 0 )
	ret << fabs( k[i] );

      if ( degree() - i >= 2 )
        ret << "x^" << degree() - i;
      else if ( degree() - i == 1 )
        ret << "x";

      ret << " ";
    }
  }

  return ret.str();
}

int main()
{
  int grad, auswahl;
  vector<double> p;

  cout << "Grad der Funktion: ";
  cin >> grad;

  p.resize( grad + 1 );
  for (int i = 0; i <= grad; i++)
  {
    cout << "Koeffizient von x^" << grad-i << ": ";
    cin >> p[i];
  }
  
  Function f( "f", p );

  while(true)
  {
    cout << "Was wollen Sie tun?" << endl
         << "[1] Funktion anzeigen" << endl
         << "[2] Funktionswert berechnen" << endl
         << "[3] Funktion ableiten" << endl
         << "[4] Nullstellen berechnen" << endl
         << "[5] Extrempunkte berechnen" << endl
         << "[6] Wendepunkte berechnen" << endl
         << "[7] Beenden" << endl
         << "Auswahl: ";

    cin >> auswahl;

    switch( auswahl )
    {
      case 1:
        cout << f.toString() << endl;
        break;

      case 2:
      {
        int i;

        cout << "Funktionswert: ";
        cin >> i;
        cout << "f(" << i << ") = " << f.f(i) << endl;
        break;
      }

      case 3:
      {
        int i;

        cout << "n-te Ableitung: ";
        cin >> i;
        cout << f.derive(i)->toString() << endl;
        break;
      }

      case 4:
      {
        list<double> v = f.roots();
        for(list<double>::iterator it = v.begin(); it != v.end(); it++)
          cout << "N(" << *it << "|0)" << endl;
        break;
      }

      case 5:
      {
        list<Point> w = f.extrema();
        for(list<Point>::iterator it = w.begin(); it != w.end(); it++)
          cout << "E(" << (*it).x() << "|" << (*it).y() << ")" << endl;
        break;
      }

      case 6:
      {        
        list<Point> w = f.derive()->extrema();
        for(list<Point>::iterator it = w.begin(); it != w.end(); it++)
          cout << "W(" << (*it).x() << "|" << (*it).y() << ")" << endl;
        break;
      }

      case 7:
        return 0;

      default:
        cerr << "Fehlerhafte Eingabe! Bitte geben sie eine Zahl zwischen 1 und 7 ein." << endl;
    }
  }
}

function.h

/*
 * Function - a program to calculate with polynomial functions
 * Copyright (C) 2005 Nicolas Bellm
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 */

#include <vector>
#include <list>
#include <string>

using namespace std;

class Point
{
 public:
  Point() { m_x = 0; m_y = 0; }
  Point(double x, double y) { m_x = x; m_y = y; }
  void setX(double x) { m_x = x; }
  void setY(double y) { m_y = y; }
  double x() { return m_x; }
  double y() { return m_y; }

 private:
  double m_x, m_y;
};

class Function
{
 public:
  Function(string name, vector<double> &_k) { m_name = name; k = _k; };
  ~Function() {}
  double f(double x);
  list<double> roots();
  Function* derive();
  Function* derive(int i);
  int degree() { return k.size() - 1; };
  list<Point> extrema();
  string toString();

 private:
  string m_name;
  vector<double> k; // Koeffizienten
};