Constructing plotting routine for a polynomial?

May 2, 2022 at 8:49am
Given this 4th order polynomial, x^4 - 3x^3 -15x^2 +10x +30, use lab 17 to construct a plotting routine from x = -3.5 to x = +5.5.
increment 0.1, by replacing the return value of the function with a0 * pow(x,4) + a1 * pow(x,3) + a2 * pow(x,2) + a3*x +a4; (drop
the if, no worries about x=0) and define, a0, a1, a2, a3 ,a4 in the function with the values from the latter equation, be careful of
signs. The output to a file ( you name in its filename) needed for plotting in excel to plot this polynomial. Plot both axis with
appropriate values from the imported values.

How would I edit this code (Lab 17) to be able to plot for this new 4th degree polynomial ? I understand I have to define the coefficients of the polynomial, but to I define them at int, or as double on line 10 in parentheses?

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
#include<iostream>		//Required for cin, cout
#include<cmath>			
#include<fstream>		// to build data file to be used by Excel to plot
#include <string>		// for using filename and
using namespace std;
double ROBBINS (double x);	//Function Prototype
int
main ()
{
  double a, b, x_incr, new_x;	// Declare objects in main()
  int Number, loop;
  string filename;
  ofstream fout;		// declare object for sending data to the output file
  cout <<
    "enter the name of the data file to send data used for plotting, from this program\n";
  cin >> filename;
  fout.open (filename);		// open file for inputing data from this program
  cout << "Enter endpoint range a and b (a<b): of the function to be plotted \n";
  cin >> a >> b;
  cout <<
    "Enter the number of points you want over the range of 'a' to 'b'\n";
  cin >> Number;
  x_incr = (b - a) / Number;	// increment between the points based on number wanted
  loop = int (b - a) / x_incr;	// loop gives the for loop repetitions equal to number points wanted
  cout << loop;			// check that shows loop and Number are the same
  cout.setf (ios::fixed);
  cout.precision (6);		// Set Formats
  cout << "x and ROBBINSX \n";
  for (int k = 0; k <= loop; k++)
    {
      new_x = a + k * x_incr;
      cout << new_x << " " << ROBBINS (new_x) << endl;	//echo vales to screen
      fout << new_x << " " << ROBBINS (new_x) << endl;	// building data file for excel plotting
    }
  return 0;			// Exit program.
  fout.close ();
}				// end main unction used on the next slide 

double ROBBINS (double x)
  if (x == 0)			
    {
      return 1;		
    }			
  else
    {
      return -exp(fabs(x)/10) /fabs(x);
    }
}				// end of function 
Last edited on May 2, 2022 at 8:51am
May 2, 2022 at 9:06am
As far as I can see, all you have to do is to remove lines 40-45 and 47. Then for L46 replace the return value of the function with a0 * pow(x,4) + a1 * pow(x,3) + a2 * pow(x,2) + a3*x +a4;

Within ROBBINS() define a0 as 1, a1 as -3, a2 as -15, a3 as 10 and a4 as 30.

Easy peasy!

Perhaps:

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

double ROBBINS(double x);

int main() {
	std::string filename;

	std::cout << "Enter the name of the data file to send data used for plotting, from this program: ";
	std::cin >> filename;

	std::ofstream fout(filename);

	if (!fout)
		return (std::cout << "Cannot open file\n"), 1;

	double a {}, b {};
	unsigned Number {};

	std::cout << "Enter endpoint range a and b (a < b) of the function to be plotted: ";
	std::cin >> a >> b;

	std::cout << "Enter the number of points you want over the range of 'a' to 'b': ";
	std::cin >> Number;

	const auto x_incr {(b - a) / Number};		// increment between the points based on number wanted
	const auto loop {unsigned((b - a) / x_incr)};	// loop gives the for loop repetitions equal to number points wanted

	//std::cout << loop;			// check that shows loop and Number are the same

	if (loop != Number)
		std::cout << "Warning! loop does not equal Number!\n";

	std::cout << std::fixed << std::setprecision(6);
	std::cout << "x and ROBBINSX \n";

	for (unsigned k {}; k <= loop; ++k) {
		const auto new_x {a + k * x_incr};

		std::cout << new_x << " " << ROBBINS(new_x) << '\n';
		fout << new_x << " " << ROBBINS(new_x) << '\n';
	}
}

double ROBBINS(double x) {
	const int a0 {1}, a1 {-3}, a2 {-15}, a3 {10}, a4 {30};

	return  a0 * std::pow(x, 4) + a1 * std::pow(x, 3) + a2 * std::pow(x, 2) + a3 * x + a4;
}

Last edited on May 2, 2022 at 12:14pm
May 2, 2022 at 9:41am
Do I replace the "double x" in ROBBINS with a0(1),a1(-3), etc? Because I tried doing that before and got an error stating that a0 was not declared.
May 2, 2022 at 10:01am
See my revised post above with code.
May 3, 2022 at 6:44am
How do you know the increment is 0.1? Is it 0.1 by default? Or does it depend on the values input on the keyboard?
May 3, 2022 at 7:54am
Blueshark1 wrote:
How do you know the increment is 0.1? Is it 0.1 by default? Or does it depend on the values input on the keyboard?


What do you think
x_incr = (b - a) / Number;
does?


BTW, it seems counterintuitive to define your polynomial with a0 multiplying the 4th power and a4 multiplying the 0th power (constant).

And the fact that it is written as a power (exponent) ... doesn't mean you should evaluate polynomials like that.
Last edited on May 3, 2022 at 8:01am
May 3, 2022 at 11:26am
Why ROBBINS? Anyway, here's a possibility with variable names that make more sense to me at least. Making it a .csv file via the comma isn't mandatory but makes it 'conventionally' easier for the spreadsheet import.

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

using namespace std;

double ROBBINS (double x);

int main ()
{
    string filename;
    cout << "Enter file name: ";
    cin >> filename;
    
   
    ofstream file(filename);
    if( !file.is_open() )
    {
        cout << "File not opened\n";
        exit(1);
    }
    
    
    double X1{-3.5}, X2{3.5}, no_points{0};
    cout << "Enter range: ";
    cin >> X1 >> X2;
    cout << "Enter number of points: ";
    cin >> no_points;
    
    
    double spacing{0.1}, x{0};
    spacing = (X2 - X1) / (no_points);
    
    
    for (int k = 0; k <= no_points; k++)
    {
        x = X1 + k * spacing;
        
        cout << x << ',' << ROBBINS (x) << '\n';
        file << x << ',' << ROBBINS (x) << '\n';
    }
    
    file.close();
    return 0;
}
double ROBBINS (double x)
{
    int a[]{30, 10, -15, -3, 1};
    size_t sz{sizeof(a)/sizeof(int)};
    double sum{0};
    
    for(int i = 0; i < sz; i++)
    {
        sum += a[i] * pow(x,i);
    }
    
    return sum;
}


Enter file name: sample.csv
Enter range: -3.3 3.5
Enter number of points: 20
-3.3,60.0531
-2.96,23.5446
-2.62,1.90817
-2.28,-8.19558
-1.94,-9.78516
-1.6,-5.5584
-1.26,2.1076
-0.92,11.1565
-0.58,19.8525
-0.24,26.7808
0.1,30.8471
0.44,31.2779
0.78,27.6205
1.12,19.7427
1.46,7.83331
1.8,-7.5984
2.14,-25.7223
2.48,-45.3876
2.82,-65.1226
3.16,-83.1353
3.5,-97.3125
Program ended with exit code: 0


https://imgur.com/a/SN1IkPc
Last edited on May 3, 2022 at 11:30am
May 3, 2022 at 11:43am
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
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

double poly( const vector<double> &c, double x )
{
   double p = 0;
   for ( int i = c.size() - 1; i >= 0; i-- ) p = c[i] + x * p;
   return p;
}

int main()
{
   vector<double> c = { 30, 10, -15, -3, 1 };
   string filename;
   double a, b;
   int n;

   cout << "Enter filename for output: ";   cin >> filename;
   ofstream out( filename );

   cout << "Enter a, b, n (for n outputs in [a,b]): ";   cin >> a >> b >> n;
   double dx = ( b - a ) / ( n - 1 );
   for ( int i = 0; i < n; i++ )
   {
      double x = a + i * dx, y = poly( c, x );
      cout << x << '\t' << y << '\n';
       out << x << '\t' << y << '\n';
   }
}


Enter filename for output: data.dat
Enter a, b, n (for n outputs in [a,b]): -3.5 5.5 19
-3.5    89.9375
-3      27
-2.5    -2.8125
-2      -10
-1.5    -3.5625
-1      9
-0.5    21.6875
0       30
0.5     30.9375
1       23
1.5     6.1875
2       -18
2.5     -46.5625
3       -75
3.5     -97.3125
4       -106
4.5     -92.0625
5       -45
5.5     47.1875



To save importing it into Excel you can plot data.dat with gnuplot:

p "data.dat" w l

or slightly minimalist Python:

1
2
3
4
5
6
7
8
import numpy as np
import matplotlib.pyplot as plt

filename = input( "Enter filename: " )
x, y = np.loadtxt( filename, unpack=True )
fig, ax = plt.subplots()
ax.plot( x, y )
plt.show()


Last edited on May 3, 2022 at 2:16pm
May 3, 2022 at 11:46am
And the fact that it is written as a power (exponent) ... doesn't mean you should evaluate polynomials like that.


Possibly like this - which avoids the overhead of pow() and only calculates the next term based upon the previous:

1
2
3
4
5
6
7
8
9
10
11
ouble ROBBINS(double x) {
	const double a[] {1, -3, -15, 10, 30};
	double val {a[4]}, x1 {1};

	for (unsigned i {4}; i > 0; --i) {
		x1 *= x;
		val += x1 * a[i - 1];
	}

	return val;
}

Last edited on May 3, 2022 at 4:10pm
Topic archived. No new replies allowed.