2014-11-20 2 views
0

Это следующий вопрос, я спросил в этой теме: Link error missing vtableметод Ньютона для вычисления обратного

Я определил «функцию» класса и два других классов «полиномиальное» и «аффинных», который наследует от «функции».

class function { 

     public: 
      function(){}; 
      virtual function* clone()const=0; 
      virtual float operator()(float x)const=0; //gives the image of a number by the function 
      virtual function* derivative()const=0; 
      virtual float inverse(float y)const=0; 
      virtual ~function(){} 

     }; 

     class polynomial : public function { 
     protected: 
      int degree; 
     private: 
      float *coefficient; 
     public: 

      polynomial(int d); 
      virtual~polynomial(); 
      virtual function* clone()const; 
      int get_degree()const; 
      float operator[](int i)const; //reads coefficient number i 
      float& operator[](int i); //updates coefficient number i 
      virtual float operator()(float x)const; 
      virtual function* derivative()const; 
      virtual float inverse(float y)const; 

     }; 

     class affine : public polynomial { 
      int a; 
      int b; 
      //ax+b 
    public: 
      affine(int d,float a_, float b_); 
      function* clone()const; 
      float operator()(float x)const; 
      function* derivative()const; 
      float inverse(float y)const; 
      ~affine(){} 
     }; 

Метод обратного в polyomial не кажется, работает хорошо. Он основан на методе Ньютона, примененном к функции x-> f (x) -y при фиксированном y (элементе, для которого мы вычисляем обратный), и текущем многочлене f.

float polynomial::inverse(float y)const 
{ 
    int i=0; 
    float x0=1; 
    function* deriv=derivative(); 
    float x1=x0+(y-operator()(x0))/(deriv->operator()(x0)); 
    while(i<=100 && abs(x1-x0)>1e-5) 
    { 
     x0=x1; 
     x1=x0+(y-operator()(x0))/(deriv->operator()(x0)); 
     i++; 
    } 

    if(abs(x1-x0)<=1e-5) 
    { 
     //delete deriv; //I get memory problems when I uncomment this line 
     return x1; 
    } 

    else  
    { 
     cout<<"Maximum iteration reached in polynomial method 'inverse'"<<endl; 
     //delete deriv; //same here 
     return -1; 
    } 
} 

double polynomial::operator()(double x)const 
{ 
    double value=0; 
    for(int i=0;i<=degree;i++) value+=coefficient[i]*pow(x,i); 
    return value; 
} 
polynomial* polynomial::derivative()const 
{ 
    if(degree==0) 
    { 
     return new affine(0,0,0); 
    } 
    polynomial* deriv=new polynomial(degree-1); 
    for(int i=0;i<degree;i++) 
     deriv[i]=(i+1)*coefficient[i+1]; 
    return deriv; 
} 

Я проверить этот метод с р: х> х^3:

#include "function.h" 

int main(int argc, const char * argv[]) 
{ 

     polynomial p(3); 
     for(int i=0;i<=2;i++) p[i]=0; 
     p[3]=1; 
     cout<<"27^(1/3)="<<p.inverse(27); 



     return 0; 
} 

Этот скрипт выводит 27^(1/3)=Maximum iteration reached in polynomial method 'inverse' -1 даже если я ставлю 10000 вместо 100. Я читал некоторые статьи в Интернете и кажется, что это обычный способ вычисления обратного.

+0

может быть, не в теме, но обязательно связан с получением кода на работу; почему вы явно вызываете оператор? как оператор() (x0); это не то, как оператор перегружает работу в C++. Вы должны просто вызвать (x0), чтобы вызвать оператор(). – Pandrei

+0

Я вызываю явно оператор со стрелкой (->), потому что «производный» - это указатель, а не экземпляр «polyiomal» – dada

+0

Если я этого не делаю, я получаю ошибку: ** Тип вызываемого типа объекта * 'не является указателем функции или функции ** – dada

ответ

0

прототип функции abs: int abs(int) Так что тест, подобный abs(x1-x0)<=1e-5, не будет вести себя так, как вы ожидаете; вы сравниваете int с поплавком. В этом случае float будет преобразован в int так же, как и abs(x1-x0)<=0

Возможно, поэтому вы не получите ожидаемого результата - я предлагаю добавить еще несколько распечаток, чтобы разобраться в деталях.

+1

Возможно, стоит упомянуть об исправлении: используйте 'std :: abs', который перегружен для типов с плавающей точкой, и обязательно включите' '. –

+0

Действительно, я использую , и я убедился, прочитав документацию, в которой он принимает во внимание. – dada

+0

@dada: Но вы называете это 'abs' не' std :: abs'. Если у вас нет неприятного загрязнения пространства имен, неквалифицированный 'abs' может ссылаться только на версию библиотеки C, которая является только целым числом. –

0

Ну, проблема была в методе «производная». Вместо использования «operator []», который я переопределил, я использовал «-> коэффициент []», а основной скрипт работал нормально для p.inverse(27) (всего 14 итераций). Я только что заменил deriv[i]=(i+1)*coefficient[i+1];deriv->coefficient[i]=(i+1)*coefficient[i+1];

+0

Но я должен упомянуть, что запуск основного скрипта с 'p.inverse (729)' выводит '15.5884', когда я начинаю с x0 = 8. Он должен нормально возвращать 9 ... – dada

Смежные вопросы