Newton's Method assignment-passing functions w/ pointer arguments

Pages: 12
I have an assignment to calculate Newton's method. In my loop it only goes to n=1 but I can't figure out why. I appreciate a quick response because my assignment is due tomorrow. I have asked my teacher a few times but I'm not getting very much help from him.

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
#include <iostream>
#include <cmath>
#include <iomanip.

using namespace std;

double f(double a, double b, double c, double d, double x) {
     double z;
     z =(a*(x*x*x))+(b*(x*x))+(c*x)+(d);
     return (z);
}
double newton(double a, double b, double c, double d, double xn){

double z;
z = f(a,b,c,d,xn);
double fprime= f(a*0, 3*a, 2*b, c, xn);
double xnplus1 = xn - ((z)/(fprime));
return (xnplus1);
}
int main() {
double a,b,c,d,z;
double xn;

cout << "Input a" << endl;
cin >> a;
cout << "Input b" << endl;
cin >> b;
cout << "Input c" << endl;
cin >> c;
cout << "Input d" << endl;
cin >> d;
cout << "What is the initial guess?" << endl;
cin >> xn;

z = f(a,b,c,d,xn);
cout << z << endl;

double fprime = f(a*0, 3*a, 2*b, c, xn);
cout << fprime << endl;
double n=0;
double xnplus1 = newton(a,b,c,d,xn);
newton(a,b,c,d,xn);
cout << "xn" << xn << endl;
cout << "xnplus1" << xnplus1 << endl;
cout << "abs" << abs(xnplus1-xn);

while (abs(xnplus1-xn)>0.00001) {
     if (n!=0) {
          xn = xnplus1;
     }else{
          xn=xn;
     }
     double xnplus1 = newton(a,b,c,d,xn);
     z = f(a,b,c,d,xn);
     double fprime = f(a*0, 3*a, 2*b, c, xn);
     newton(a,b,c,d,xn);
     n++; 
}
return 0;
}

  
Last edited on
I didn't follow what you were trying to do in the while loop. Possibly it should look something like this:
47
48
49
50
51
52
53
    while (abs(xnplus1-xn) > 0.00001)
    {
        xn = xnplus1;
        xnplus1 = newton(a,b,c,d,xn);
        n++;
        cout << "n: " << n << "  xn: " << xn << endl;
    }
What I' was trying to do was for the first iteration xn needs to equal what the user entered but from the second one on it needs to enter xnplus1, just like I'm newtons method.
Yes, but you already did the first iteration before entering the loop. At line 41.

Note , line 42 doesn't do anything.
Hi there,

use "fabs" instead of "abs" and it might work... in your "condition" for the while loop ...
And tell me if it helped. I only know that issue from "raw C" ... there it makes a difference.

And i also do not understand why you take your stepsize as a termination condition. At least you solve "f=0" (or ?), so you should use

1
2
while(fabs(f(a, b, c, xnplus1) > tol){ ........
}


i think.

And then you can (and i think you better do) leave out
1
2
3
4
5
 if (n!=0) {
          xn = xnplus1;
     }else{
          xn=xn;
     }




Last edited on
Using fabs doesn't change anything for me. I did however change the while loop and now it computes the root correctly! Which is a huge relief but, what I didn't include with the instructions is that I have to print out the n,xn, f(xn), f'(xn), xN+1, and abs(xn-xn+1). I have it all printed out except that every time it prints f(xn) it prints the same number and every time I print f'(xn) it prints the same number for each iteration of n . This may just be something simple I need to look at when I get the chance after classes, but any help is once again appreciated.
Thank you guys soo much.
Oh. Yeah all I needed to do was put z=f(a,b,c,d,xn) and fprime=f(a*0,3*a,2*b,c,xn) inside the loop and worked fine.
The last part of the assignment is putting in pointers to variables of both of the two functions, which I THINK I will be able to figure out without losing too much hair. Thanks for your help you two.
Just one comment. I would have made a separate function for fprime, perhaps like this:
.
1
2
3
4
5
6
7
8
9
double f(double a, double b, double c, double d, double x) 
{
    return  a*(x*x*x)  +  b*(x*x)  +  c*x  +  d;
}

double fprime(double a, double b, double c, double d, double x) 
{
    return f(0, 3*a, 2* b, c, x);
}
I did that at first Chervil, until I read the instructions for what we were supposed to do. We had to have them in the same function with a general expression that manipulate to get the derivative.

I'm now kind of stuck on putting pointers in the functions. All i did to change it from there so far is put the * in front of the variables in the function argument and then I thought whenever I call it that it needs to just have & in front of it but apparently not. The fprime function is also causing fits because of the 3*a and 2*b arguments...

I'm obviously new to this sorry for what probably sound like really beginner level questions.
Hi again,

using pointers would lokk like this:

1
2
3
4
5
6
7
8
9
10

double f(double* a, double *b, double *c, double *d, double *x){

// some initializing etc.
// and don't forget to "dereference" when calculating:

out = *a * (x*x*x) + ....

// if a is a pointer, *a is the value it points to ...
}

The reason to do so might be, that it is possible to "call by reference",
do you know what that means ?

A common mistake is to do sth like &4 ...
you'll have to first initialize variables as double var = 4 and then you can use &var

Last edited on
Okay so I put double var1 = 2; and double var2 = 3; right before I call the function. Then I wrote
double fprime = f(0, &var2*&a, &b * &var1, &c, &xn);

But the error message says "invalid operands of types 'double' and 'double**' to binary 'operator*'
and "invalid operands of types 'double**' and 'double' to binary 'operator*'
Last edited on
Okay yes the only problem with the program now is that it won't compile due to the fprime function. I tried what I put above as well as other combinations of things but I can't quite figure out how to get it to work.
Sorry I keep posting on here.

Since I've made so many changes I'm just going to post the whole code again. I ended up changing some things so that it would compile but now I get segmentation fault (cored dumped). This is what I now have.

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
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;
double f(double *a, double *b, double *c, double *d, double *x) {
     double z;
     z=(*a*(*x**x**x))+(*b*(*x**x))+ (*c**x)+(*d);
     return (z);
}
double newton(double *a, double *b, double *c, double *d, double *xn) {
     double z;
     z=f(a,b,c,d,xn);
     double fprime= f(0,a,b,c,xn);
     double xnplus1= *xn-((z)/(fprime));
     return (xnplus1);
}
int main() {
     double a,b,c,d,z;
     double xn;
     cout << "Input a" << endl;
     cin >> a;
     cout << "Input b" << endl;
     cin >> b;
     cout << "Input c" << endl;
     cin >> c;
     cout << "Input d" << endl;
     cin >> d;
     cout << "What is the initial value guess?" << endl;
     cin >> xn;
     z = f(&a,&b,&c,&d,&xn);
     d=c;
     a=a*3;
     b=b*2;
     double fprime = f(0,&a,&b,&d,&xn);
cout << "---------------------------------------"<< endl;
     cout <<setw(0) << "N"
     <<setw(16)<<fixed<<setprecision(6)<< "xN"
     <<setw(16)<<fixed<<setprecision(6)<< "f(xN)"
     <<setw(16)<<fixed<<setprecision(6)<< "f'(xN)"
     <<setw(16)<<fixed<<setprecision(6)<< "xN +1"
     <<setw(24)<<fixed<<setprecision(6)<< "abs(xN-xN+1)"
     << endl;
     
     double n=0;
     double xnplus1=newton(&a,&b,&c,&d,&xn);
          newton(&a,&b,&c,&d,&xn);
          cout <<fixed<<setprecision(0)<< n 
          <<setw(16)<<fixed<<setprecision(6)<< xn
          <<setw(16)<<fixed<<setprecision(6)<< z
          <<setw(16)<<fixed<<setprecision(6)<< fprime
          <<setw(16)<<fixed<<setprecision(6)<< xnplus1
          <<setw(24)<<fixed<<setprecision(6)<< abs(xn-xnplus1)
          << endl;
     while((abs(xn-xnplus1))>0.00001) {
          xn=xnplus1;
          xnplus1=newton(&a,&b,&c,&d,&xn);
          z=f(&a,&b,&c,&d,&xn);
          d=c;
          a=a*3;
          b=b*2;
          fprime = f(0,&a,&b,&d,&xn);
          cout << fixed << setprecision(0) << n 
          <<setw(16)<<fixed<<setprecision(6) << xn
          <<setw(16)<<fixed<<setprecision(6)<< z
          <<setw(16)<<fixed<<setprecision(6)<< fprime
          <<setw(16)<<fixed<<setprecision(6)<< xnplus1
          <<setw(24)<<fixed<<setprecision(6)<< abs(xn-xnplus1)
          << endl;

           n++;
      }
      return 0;
}

Don't program with pointers if you don't really need them. They can get you into trouble. f(0,...) is the problem for your segmentation fault. Don't use 0 as a pointer
Oh trust me I wouldn't, it's just part of the assignment we have to use pointers.

Well I changed to where double j =a*0; and put &j in place of the zero in the two times I call the function in main. It stopped the immediate cored dump but then after it made the headers to the table, the core dumped. Does it have something to do with how I called the functions in the newton function? I thought I'd put ampersands in front of them as well but it would never compile like that.

The program dumps the core right after it prints "abs(xN-xN+1)"
Last edited on
Anyone?
Well ats15 already identified the problem with passing 0 where the function expects a pointer to a double. This was my quick attempt to fix it. I defined a constant like this:
 
const double zero = 0.0;

I made it constant as clearly I don't want to accidentally change the value. That meant in order to keep everything consistent, making the function parameters const too. There are other solutions, including simply leaving zero as an ordinary variable, but unless the function really needs to alter the value of its variables, they should be const in any case.
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
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

const double zero = 0.0;

double f(const double *a, const double *b, const double *c, const double *d, const double *x)
{
     double z;
     z=(*a*(*x**x**x))+(*b*(*x**x))+ (*c**x)+(*d);
     return (z);
}

double newton(const double *a, const double *b, const double *c, const double *d, const double *xn)
{
     double z;
     z=f(a,b,c,d,xn);
     double fprime= f(&zero,a,b,c,xn);
     double xnplus1= *xn-((z)/(fprime));
     return (xnplus1);
}

int main() {

     double a,b,c,d,z;
     double xn;
     cout << "Input a" << endl;
     cin >> a;
     cout << "Input b" << endl;
     cin >> b;
     cout << "Input c" << endl;
     cin >> c;
     cout << "Input d" << endl;
     cin >> d;
     cout << "What is the initial value guess?" << endl;
     cin >> xn;
     z = f(&a,&b,&c,&d,&xn);
     d=c;
     a=a*3;
     b=b*2;
     double fprime = f(&zero,&a,&b,&d,&xn);
cout << "---------------------------------------"<< endl;
     cout <<setw(0) << "N"
     <<setw(16)<<fixed<<setprecision(6)<< "xN"
     <<setw(16)<<fixed<<setprecision(6)<< "f(xN)"
     <<setw(16)<<fixed<<setprecision(6)<< "f'(xN)"
     <<setw(16)<<fixed<<setprecision(6)<< "xN +1"
     <<setw(24)<<fixed<<setprecision(6)<< "abs(xN-xN+1)"
     << endl;

     double n=0;
     double xnplus1=newton(&a,&b,&c,&d,&xn);
          newton(&a,&b,&c,&d,&xn);
          cout <<fixed<<setprecision(0)<< n
          <<setw(16)<<fixed<<setprecision(6)<< xn
          <<setw(16)<<fixed<<setprecision(6)<< z
          <<setw(16)<<fixed<<setprecision(6)<< fprime
          <<setw(16)<<fixed<<setprecision(6)<< xnplus1
          <<setw(24)<<fixed<<setprecision(6)<< abs(xn-xnplus1)
          << endl;
     while((abs(xn-xnplus1))>0.00001) {
          xn=xnplus1;
          xnplus1=newton(&a,&b,&c,&d,&xn);
          z=f(&a,&b,&c,&d,&xn);
          d=c;
          a=a*3;
          b=b*2;
          fprime = f(&zero,&a,&b,&d,&xn);
          cout << fixed << setprecision(0) << n
          <<setw(16)<<fixed<<setprecision(6) << xn
          <<setw(16)<<fixed<<setprecision(6)<< z
          <<setw(16)<<fixed<<setprecision(6)<< fprime
          <<setw(16)<<fixed<<setprecision(6)<< xnplus1
          <<setw(24)<<fixed<<setprecision(6)<< abs(xn-xnplus1)
          << endl;

           n++;
      }
      return 0;
}
Thank you that got it working, it is just that, say when running the program I enter in 0,3,-2,-1, and an initial guess of 10, it should only run through n=7 iterations. But it does 31 iterations. The first xN, f(xN), and f'(xN) are correct but starting with xN+1, from then on everything is wrong. I'm trying to figure out what went wrong but everything looks okay to me...
I really don't have a good feeling about the way you are modifying the coefficients (repeatedly) like this:
1
2
3
     d=c;
     a=a*3;
     b=b*2;

Surely this means the equation which is being solved is never the same from one iteration to the next. Perhaps you should define three new variables to pass to the function when calculating fprime. Because of the way your code is structured, you will need to do this just once in main(), and again in function newton()
Last edited on
Okay I fixed it like you said, and did the other things we were supposed to do for the assignment and got it finished. Thank you so much for your help!
Pages: 12