Having trouble implementing the concept of an derivative with an array of doubles

I am working on a class called polynomial, and one of the things I need to do in the class is find the derivative of polynomials. I use an array of doubles to represent the polynomials, such that the index corresponds to the power of 'x' and the data at that index corresponds to the coefficient. For example;

a0(x^0)+a1(x^1)+a2(x^2)...+an-1(x^n-1)+an(x^n)

is represented in an array of doubles as:

double fx[n];

fx[0] = a0
fx[1] = a1
...
fx[n] = an

To implement a derivative I am using the power rule, basically multiplying the index by the coefficient and store that in another array with the index decremented by one.

f'(x^3+3x^2+6x+2) = 3x^2+6x+6. <- another polynomial

Here is my code thus far. The relevant members are data* fx which holds the coefficients of the polynomial, and the polynomial* deriv which is supposed to point to that polynomials derivative. I am implementing a derivative chain down to x^1 in a recursive way, using the private constructor polynomial(const polynomial&, unsigned);

header file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef _POLY_H_ 
      #define _POLY_H_ 
      
#include <iostream>
#include <iomanip>

using namespace std;

const unsigned timeout = 200;
const unsigned displayPrecision = 3;
      
class polynomial
{
    double* fx;
    unsigned polyDegree;
    double* critPnts;
    unsigned numCritPnts;
    double* realRoots;
    unsigned numRealRoots;
    polynomial* deriv;
    
    polynomial(const polynomial&, unsigned);
    
public:
    polynomial(const double*, unsigned);
    polynomial(const polynomial&);
    ~polynomial();
    void solve(unsigned precision = 0.001);
    polynomial retrieveF(unsigned);
    void write();
    
    friend ostream& operator<< (ostream& os, const polynomial& p);
};

#endif 



implementation file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "polynomial.h"

polynomial::polynomial(const double* func, unsigned l)
:polyDegree(l),critPnts(NULL), numCritPnts(0), realRoots(NULL), numRealRoots(0), deriv(NULL)
{
    fx =  new double[l];
    
    for(int i = 0; i <= l; i++)
    {
        fx[i] = func[i];
    }
}

polynomial::polynomial(const polynomial& f, unsigned l)
:polyDegree(l),critPnts(NULL), numCritPnts(0), realRoots(NULL), numRealRoots(0), deriv(NULL)
{
    fx =  new double[l];
    
    for(int i = 1; i <= l; i++)
    {
        fx[i-1] = f.fx[i] * i;
    }
    
    cout << *this << endl;
}

polynomial::polynomial(const polynomial& f)
{
    fx = new double(f.polyDegree);
    critPnts = new double(f.numCritPnts);
    realRoots = new double(f.numRealRoots);
    
    polyDegree = f.polyDegree;
    numCritPnts = f.numCritPnts;
    numRealRoots =  f.numRealRoots;
    
    for(int i = 0; i <= polyDegree; i++)
    {
        fx[i] = f.fx[i];
    }
    
    for(int i = 0; i <= numCritPnts; i++)
    {
        fx[i] = f.fx[i];
    }
    
    for(int i = 0; i <= numRealRoots ; i++)
    {
        fx[i] = f.fx[i];
    }
}

polynomial::~polynomial()
{
    polynomial* temp = this;
    
    do
    {
        delete[] temp->fx;
        delete[] temp->critPnts;
        delete[] temp->realRoots;
        temp = temp->deriv;
    } while (temp != NULL);
        
}

void polynomial::solve(unsigned precision)
{
    if (polyDegree == 0)
    {
        return;
    }
    
    if (polyDegree > 1)
    {
        deriv =  new polynomial(*this, polyDegree-1);
        deriv->solve();
    }
        
}

polynomial polynomial::retrieveF(unsigned)
{
}

void polynomial::write()
{
}

ostream& operator<< (ostream& os, const polynomial& p)
{
    
    if(p.polyDegree >= 2)
    {
    os << fixed << setprecision(displayPrecision) << p.fx[p.polyDegree] << "x^" << p.polyDegree << " ";
    }
    
    for (int i = p.polyDegree-1; i >= 2; i--)
    {
        if (p.fx[i] > 0)
        {
            os << "+ " << fixed << setprecision(displayPrecision) << p.fx[i] << "x^" << i << " ";
        } 
        else
        {
            os << "- " << fixed << setprecision(displayPrecision) << p.fx[i]* -1 << "x^" << i << " ";
        }
    }
        
        if (p.fx[1] > 0)
        {
            os << "+ " << fixed << setprecision(displayPrecision) << p.fx[1] << "x ";
        } 
        else
        {
            os << "- " << fixed << setprecision(displayPrecision) << p.fx[1]* -1 << "x ";
        }
        
        if (p.fx[0] > 0)
        {
            os << "+ " << fixed << setprecision(displayPrecision) << p.fx[0];
        } 
        else
        {
            os << "- " << fixed << setprecision(displayPrecision) << p.fx[1]* -1;
        }
}


main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include "polynomial.h"

int main()
{
    double test[5] = {1.0,-2.0,3.0,-4.0,5.0};
    
    polynomial p(test, 4); 
    
    cout << p << endl;
    
    p.solve();
    
    cin.get();
    
    return 0;
}


The ouput I get to the screen looks like this:


5.000x^4 - 4.00x^3 + 3.000x^2 - 2.000x + 1.000
0.000x^3 - 12.000x^2 + 6.000x - -6.000
0.000x^2 - 24.000x + 6
+0.000x - -0.000


If I removed the fixed flag the elements that are showing up as zeros show up as rather odd numbers instead, something like 2.714e-308 or something similar. This is really odd and I don't know exactly why.

I am getting a warning about using this instruction deriv->solve(). I have a default unsigned parameter that is intended to be used to set the precision of another feature I haven't implemented. I am getting the warning:

[warning]converting to 'unsigned int' from 'double'
.

I don't really know what that means or if that is somehow effecting my code. If someone could help me implement the same concept in a better way I would appreciate it, as I suspect it is the cause of my problem somehow.

Thank you for any help. I am really stuck and could use a point in the right direction.
> [warning]converting to 'unsigned int' from 'double'
void solve(unsigned precision = 0.001); unsigned is short for unsigned int (an integer). The compiler is telling you that it will use 0

1
2
3
4
5
6
7
8
9
10
11
//polynomial p(test, 4); 
polynomial::polynomial(const double* func, unsigned l)
:polyDegree(l),critPnts(NULL), numCritPnts(0), realRoots(NULL), numRealRoots(0), deriv(NULL)
{
    fx =  new double[l];
    
    for(int i = 0; i <= l; i++)
    {
        fx[i] = func[i];
    }
}
That's wrong. fx has size `l', so that means that the index goes from 0 to `l-1'.

1
2
3
4
5
6
7
8
9
10
11
12
13
// deriv =  new polynomial(*this, polyDegree-1);
polynomial::polynomial(const polynomial& f, unsigned l)
:polyDegree(l),critPnts(NULL), numCritPnts(0), realRoots(NULL), numRealRoots(0), deriv(NULL)
{
    fx =  new double[l];
    
    for(int i = 1; i <= l; i++)
    {
        fx[i-1] = f.fx[i] * i;
    }
    
    cout << *this << endl;
}
Now here you access coefficients 1 to 3 from the original polynomial (ignoring a_4)


It's confusing to use a constructor to derive. You better make it a method.
Also, be careful with memory leaks.
Thank you.

I realized just after you posted that my loop wasn't running enough times. I left polyDegree undecremented in the function call (so now its one larger) and changed my deriv constructor to the following. :

1
2
3
4
5
6
7
8
9
10
11
12
polynomial::polynomial(const polynomial& f, unsigned l)
:polyDegree(l-1),critPnts(NULL), numCritPnts(0), realRoots(NULL), numRealRoots(0), deriv(NULL)
{
    fx =  new double[l];
    
    for(int i = 1; i <= l; i++)
    {
        fx[i-1] = f.fx[i] * i;
    }
    
    cout << *this << endl;
}


It works better, but for whatever reason the first index is not always coming out correctly. The output from this is:


5.000x^4 - 4.000x^3 + 3.000x^2 -  2.000x + 1.000
20.000x^3 - 12.000x^2 +6.000x - -6.000
60.000x^2 - 24.000x + 6.000
+ 120.000x - -120.000


On line two - -6.000 should be - 2.000. Also, the last line output is incorrect as well, the second number should be a negative 24. I seem to have an issue with the first iteration of the loop but I am not sure what that issue is.

Also, when you say that the compiler will use zero, does this mean the function will be called with zero and my precision variable will be overwritten? Is this something I need to worry about?

Thank you again.
Last edited on
Considering that you have - -6.000 instead of just + 6.000 suggest a problem in your printing function.


> Also, when you say that the compiler will use zero, does this mean the function will be called with zero and my precision variable will be overwritten? Is this something I need to worry about?
You ask for an integer, but passed a rational. The number will be truncated.
┬┐How does that affect your program? The variable is called precision but it's passed to a derive function (that we know ``exact'') that's called solve. Beats me.
Your a genuis. Implemented a simpler os friend function, everything looking good.

I don't know how I didn't see the casting issue with solve(). Its like really obvious, but I completely looked over it for some reason... thank you. I am going to tentatively mark this thread as 'solved'.
Topic archived. No new replies allowed.