Here is my attempt to implement a program that finds GCD of two polynomials.
I realize there is a problem in division method. A while loop decrementing the degree of a resulting polynomial in division() goes into "infinity" in some cases, and I can't understand in which exactly.
Any clues on what goes wrong here?
#include<iostream>
#include<stdlib.h>
using namespace std;
//polynomial------------------------------
struct polynomial {
float *coeff;
int degree;
};
/*function declaration */
int get_data(polynomial *P);
int display(polynomial *P);
int division(polynomial *P, polynomial *Q, polynomial *H, polynomial *R);
int polcpy(polynomial *p, polynomial *q);
void GCDPol(polynomial *P,polynomial *Q, polynomial *R);
//GCD of two polynomials------------------
void GCDpol(polynomial *P,polynomial *Q, polynomial *R) {
polynomial *res, *v;
res = (polynomial *) calloc(1,sizeof(polynomial));
v = (polynomial *) calloc(1,sizeof(polynomial));
while(1) {
division(P, Q, v, R);
if(R->degree==0 && R->coeff[0]==0)
break;
else
polcpy(P,Q);
polcpy(Q,R);
}
polcpy(R,Q);
free(res);
free(v);
}
//pol copy--------------------------------
int polcpy(polynomial *p, polynomial *q) {
p->degree=q->degree;
p->coeff = new float[p->degree + 1];
for (int i=0; i<=p->degree; i++)
p->coeff[i]=q->coeff[i];
return 0;
}
//division--------------------------------
int division(polynomial *P, polynomial *Q, polynomial *H, polynomial *R) {
float u;
int x;
polynomial *nh, *nr;
nh = (polynomial *) calloc(1,sizeof(polynomial));
nr = (polynomial *) calloc(1,sizeof(polynomial));
/*Euclidian Long Division*/
polcpy(nr, P);
nh->degree = P->degree - Q->degree;
nh->coeff = new float[nh->degree + 1];
for (int i=nh->degree; i>=0; i--) {
nh->coeff[i] = nr->coeff[nr->degree] / Q->coeff[Q->degree];
for (int j=i; j <= nr->degree; j++) {
u = nh->coeff[i] * Q->coeff[j-i];
nr->coeff[j] = nr->coeff[j] - u;
}
if (nr->degree > 0)
nr->degree--;
}
/*Quotient*/
polcpy(H, nh);
/*Remainder*/
polcpy(R, nr);
while(R->coeff[R->degree] == 0) {
R->degree--;
}
free(nh);
free(nr);
return 0;
}
//display-------------------------------
int display(polynomial *P) {
int i, j;
for (i = P->degree; i >= 0; i--) {
cout << P->coeff[i] << "x^" << i;
if ((i - 1) != -1)
cout << "+";
}
cout << "\n";
return 0;
}
//get_data------------------------------
int get_data(polynomial *P) {
cout << "Enter Degree Of Polynomial:";
cin >> P->degree;
P->coeff = new float[P->degree + 1];
for (int i = P->degree; i >= 0; i--) {
cout << "Enter coefficient of x^" << i << ":";
cin >> P->coeff[i];
}
return 0;
}
int main() {
polynomial *P, *Q, *R, *H;
P = (polynomial *) calloc(1,sizeof(polynomial));
Q = (polynomial *) calloc(1,sizeof(polynomial));
R = (polynomial *) calloc(1,sizeof(polynomial));
H = (polynomial *) calloc(1,sizeof(polynomial));
cout<<"GDC\n";
get_data(P);
get_data(Q);
cout << "Polynomial1:";
display(P);
cout << "Polynomial2:";
display(Q);
GCDpol(P,Q,R);
display(R);
free(R);
free(P);
free(Q);
free(H);
return 0;
}
It seems likely that the line
if(R->degree==0 && R->coeff[0]==0)
break;
is what's broken. Your coefficients are floats. Because computers are (unfortunately) finite, there will be small errors in your float computation. The code only exits the while loop if the coefficient is exactly 0. It seems likely that on some inputs, although it should divide evenly, you get R->coeff[0] = 0.0000000001 or some other very small value that is not exactly 0.
Try checking if the absolute value is within some very small tolerance (something like 10^-10 or 10^-12.) If you actually want the exact value, you'll need to look into exact precision floats, which is its own can of worms.
(Looking at the code more closely, you do exact equality checks in other places too - these should all be changed to checking the absolute value is very small.)
while(R->coeff[R->degree] == 0) {
R->degree--;
}
This goes badly wrong if R is the zero polynomial.
This C++ library implements polynomial division: PolynomialDivHang_test_no_hang
Related
I am getting a segmentation fault error when compiling my code. I don't know how to fix it. I am supposed to compile my Polynomial.cpp with my professor's poly_check.o, but I get a segmentation fault error.
This is my Polynomial.h:
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
using namespace std;
class Polynomial {
private:
double *coefficients;
int size;
public:
Polynomial();
Polynomial(double c[], int size);
Polynomial(const Polynomial &poly);
~Polynomial();
void set(double c[], int size);
inline int getDegree() const {
return size - 1;
}
double f(double x)const;
bool operator== (const Polynomial &poly)const;
Polynomial operator+ (const Polynomial &poly)const;
friend ostream & operator << (ostream &out, const
Polynomial &poly);
friend istream & operator >> (istream &in, Polynomial
&poly);
};
#endif
This is my Polynomial.cpp:
#include "Polynomial.h"
#include <iostream>
#include <cmath>
using namespace std;
Polynomial::Polynomial() {
size = 0;
coefficients = NULL;
}
Polynomial::Polynomial(double c[], int size) {
this->size = size;
coefficients = new double[size];
for (int i = 0; i < size; i++) {
coefficients[i] = c[i];
}
}
Polynomial::Polynomial(const Polynomial &poly) {
if (coefficients != NULL)
delete coefficients;
this->size = poly.size;
coefficients = new double[size];
for (int i = 0; i < size; i++)
coefficients[i] = poly.coefficients[i];
}
Polynomial::~Polynomial() {
if (coefficients != NULL)
delete coefficients;
}
void Polynomial::set(double c[], int size) {
this->size = size;
if (coefficients != NULL)
delete coefficients;
coefficients = new double[size];
for (int i = 0; i < size; i++)
coefficients[i] = c[i];
}
double Polynomial::f(double x)const {
double value = 0.0;
for (int i = 0; i < size; i++) {
value += (coefficients[i] * pow(x, i));
}
return value;
}
bool Polynomial::operator== (const Polynomial &poly)const {
if (this->size != poly.size)
return false;
for (int i = 0; i < size; i++) {
if (poly.coefficients[i] != coefficients[i])
return false;
}
return true;
}
Polynomial Polynomial::operator+ (const Polynomial &poly)const {
int maxSize = size;
if (poly.size > maxSize)
maxSize = poly.size;
double sum[maxSize] = {0.0};
for (int i = 0; i < size; i++) {
sum[i] = coefficients[i];
}
for (int i = 0; i < poly.size; i++) {
sum[i] += poly.coefficients[i];
}
Polynomial sumP(sum, maxSize);
return sumP;
}
ostream &operator << (ostream &out, const Polynomial &poly) {
for (int i = poly.size - 1; i >= 0; i--) {
if (i != poly.size - 1) {
if (poly.coefficients[i] >= 0)
out << " + ";
else
out << " - ";
}
out << poly.coefficients[i];
if (i == 0)
continue;
if (i == 1)
out << "x";
else
out << "x^" << i;
}
return out;
}
istream &operator >> (istream &in, Polynomial &poly) {
int degree;
in >> degree;
double c[100];
int size = 0;
while (in >> c[size]) {
size++;
if ((size-1) == degree)
break;
}
poly.set(c, size);
return in;
}
This is my poly_test.cpp:
#include "Polynomial.h"
#include <iostream>
using namespace std;
int main(void) {
double c1[] = {0, 1, 2, 3, 4};
double c2[] = {0, 1, 2, 3, 4, 5, 6};
Polynomial p1(c1, 5);
Polynomial p2(c2, 7);
Polynomial p3;
cout << "Enter p3: ";
cin >> p3;
cout << "p1: ";
cout << p1 << endl;
cout << "p2: ";
cout << p2 << endl;
cout << "p3: ";
cout << p3 << endl;
Polynomial p4;
p4 = p1 + p2;
cout << "p4 = p1 + p2, p4: ";
cout << p4 << endl;
double value = p1.f(2);
cout << "Evaluating p1 at x = 2, p1 = ";
cout << value << endl;
Polynomial p6(c1, 5);
cout << "p6: ";
cout << p6 << endl;
if (p6 == p1) {
cout << "p6 and p1 are equal. Equality test passed" <<
endl;
}
else {
cout << "Equality test failed" << endl;
}
return 0;
}
This is the error that I am getting:
segmentation fault error
In general, you should test your own code as you develop it. Don't write this much code and then plug it into a test function; it will fail, and the process of debugging it will be long and discouraging.
The specific problem (or one of them) is that you neglected to implement operator=. Are you familiar with shallow copies and deep copies? The default copy constructor is a shallow copier, so that two instances of Polynomial wind up with pointers to the same array. Then when they die, they both try to delete it.
I'm doing a project for university but I encountered an exception which I don't understand. I'm using S.Sahni algorithms, so mostly I've got the code from his book. What I'm trying to do is to implement the Bin Packing problem with First Fit while I'm using tournament trees (max winner).
Here is my header:
// file winner.h
#ifndef WinnerTree_
#define WinnerTree_
#include <iostream>
#include <stdlib.h>
#include "xcept.h"
using namespace std;
template<class T>
class WinnerTree {
public:
WinnerTree(int TreeSize = 10);
~WinnerTree() {delete [] t;}
void Initialize(T a[], int size, int (&winner)(T a[], int player1, int player2));
int Winner()
{return (n) ? t[1] : 0;}
int Winner(int i)
{return (i < n) ? t[i] : 0;}
void RePlay(int i, int (&winner)(T a[], int player1, int player2));
void Output();
private:
int MaxSize;
int n; // current size
int LowExt; // lowest-level external nodes
int offset; // 2^k - 1
int *t; // array for winner tree
T *e; // element array
void Play(int p, int lc, int rc, int (&winner)(T a[], int player1, int player2));
};
template<class T>
WinnerTree<T>::WinnerTree(int TreeSize)
{// Constructor for winner tree.
MaxSize = TreeSize;
t = new int[MaxSize];
n = 0;
}
template<class T>
void WinnerTree<T>::Initialize(T a[], int size, int (&winner)(T a[], int player1, int player2))
{// Initialize winner t for array a.
if (size > MaxSize || size < 2)
throw BadInput();
n = size;
e = a;
// compute s = 2^log (n-1)
int i, s;
for (s = 1; 2*s <= n-1; s += s);
LowExt = 2*(n-s);
offset = 2*s-1;
// play matches for lowest-level external nodes
for (i = 2; i <= LowExt; i += 2)
Play((offset+i)/2, i-1, i, winner);
// handle remaining external nodes
if (n % 2) {// special case for odd n, play
// internal and external node
Play(n/2, t[n-1], LowExt+1, winner);
i = LowExt+3;}
else
i = LowExt+2;
// i is left-most remaining external node
for (; i <= n; i += 2)
Play((i-LowExt+n-1)/2, i-1, i, winner);
}
template<class T>
void WinnerTree<T>::Play(int p, int lc, int rc, int (&winner)(T a[], int player1, int player2))
{// Play matches beginning at t[p].
// lc and rc are the children of t[p].
t[p] = winner(e, lc, rc);
// more matches possible if at right child
while (p > 1 && p % 2) {// at a right child
t[p/2] = winner(e, t[p-1], t[p]);
p /= 2; // go to parent
}
}
template<class T>
void WinnerTree<T>::RePlay(int i, int(&winner)(T a[], int player1, int player2))
{// Replay matches for element i.
if (i <= 0 || i > n)
throw OutOfBounds();
int p, // match node
lc, // left child of p
rc; // right child of p
// find first match node and its children
if (i <= LowExt) {// begin at lowest level
p = (offset + i)/2;
lc = 2*p - offset; // left child of p
rc = lc+1;}
else {
p = (i-LowExt+n-1)/2;
if (2*p == n-1) {
lc = t[2*p];
rc = i;}
else {
lc = 2*p - n + 1 + LowExt;
rc = lc+1;}
}
t[p] = winner(e, lc, rc);
// play remaining matches
p /= 2; // move to parent
for (; p >= 1; p /= 2)
t[p] = winner(e, t[2*p], t[2*p+1]);
}
template<class T>
void WinnerTree<T>::Output()
{
cout << "size = "<< n << " LowExt = " << LowExt
<< " Offset = " << offset << endl;
cout << "Winner tree pointers are" << endl;
for (int i = 1; i < n; i++)
cout << t[i] << ' ';
cout << endl;
}
#endif
This is my exception file:
#ifndef Xcept_
#define Xcept_
#include <exception>
#include <new.h>
// bad initializers
class BadInitializers {
public:
BadInitializers() {}
};
// insufficient memory
class NoMem {
public:
NoMem() {}
};
// change new to throw NoMem instead of xalloc
void my_new_handler()
{
throw NoMem();
};
new_handler Old_Handler_ = set_new_handler(my_new_handler);
// improper array, find, insert, or delete index
// or deletion from empty structure
class OutOfBounds {
public:
OutOfBounds() {}
};
// use when operands should have matching size
class SizeMismatch {
public:
SizeMismatch() {}
};
// use when zero was expected
class MustBeZero {
public:
MustBeZero() {}
};
// use when zero was expected
class BadInput {
public:
BadInput() {}
};
#endif
And this is my main function:
// First fit bin packing
#include "stdafx.h"
using namespace std;
#include <iostream>
#include "winner.h"
int winner(int a[], int player1, int player2)
{// For a max winner tree.
if (a[player1] >= a[player2])
return player1;
return player2;
}
void FirstFitPack(int s[], int n, int c)
{// Output first fit packing into bins of size c.
// n is the number of objects and s[] their size.
WinnerTree<int> *W = new WinnerTree<int>(n);
int *avail = new int[n + 1]; // bins
// initialize n bins and winner tree
for (int i = 1; i <= n; i++)
avail[i] = c; // initial available capacity
W->Initialize(avail, n, winner);
// put objects in bins
for (int i = 1; i <= n; i++) {// put s[i] in a bin
// find first bin with enough capacity
int p = 2; // start search at left child of root
while (p < n) {
int winp = W->Winner(p);
if (avail[winp] < s[i]) // first bin is in
p++; // right subtree
p *= 2; // move to left child
}
int b; // will be set to bin to use
p /= 2; // undo last left child move
if (p < n) {// at a tree node
b = W->Winner(p);
// if b is right child, need to check
// bin b-1. No harm done by checking
// bin b-1 even if b is left child.
if (b > 1 && avail[b - 1] >= s[i])
b--;
}
else // arises when n is odd
b = W->Winner(p / 2);
cout << "Pack object " << i << " in bin "
<< b << endl;
avail[b] -= s[i]; // update avail. capacity
W->RePlay(b, winner);
getchar();
}
}
int main(void)
{
int n, c; // number of objects and bin capacity
cout << "Enter number of objects" << endl;
cin >> n;
if (n < 2) {
cout << "Too few objects" << endl;
exit(1);
}
cout << "Enter bin capacity" << endl;
cin >> c;
int *s = new int[n + 1];
for (int i = 1; i <= n; i++) {
cout << "Enter space requirement of object " << i << endl;
cin >> s[i];
if (s[i] > c) {
cout << "Object too large to fit in a bin" << endl;
exit(1);
}
}
FirstFitPack(s, n, c);
return 0;
}
The exception that I get is:
First-chance exception at 0x0012668D in Bin Packing-FF.exe: 0xC0000005: Access violation reading location 0xF9039464.
I know that I'm getting this exception because of the winner. But I can't understand what I have to change here.
int winner(int a[], int player1, int player2)
{// For a max winner tree.
if (a[player1] >= a[player2])
return player1;
return player2;
}
Also, If I press space or enter after the last input (object) then I don't get the exception and everything is going smoothly. But still I want to know why I'm getting this exception.
Thank you in advance.
all. I'm trying to set up a program that evaluates a polynomial depending on the user input of X. Another part of the program I want is to then add these polynomials together. I'm using a 2D array to do this. What do you think would be the best way to write the evaluation function. Been working at this for hours and I'm still not quite sure how to do it. Thanks in advance.
polynomial.h
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
using namespace std;
#define MAX 100
class Polynomial {
friend ostream &operator<< (ostream &, const Polynomial &);
public :
Polynomial ();
void enterTerms();
int evaluate(Polynomial p, int x);
Polynomial operator +(const Polynomial & );
private :
int terms[MAX][2]; //either static size(MAX rows) or use "new" for dynamic allocation
int n; //number of terms
};
#endif
polynomial.cpp
#include "polynomial.h"
using namespace std;
ostream &operator<< (ostream & out, const Polynomial & p){
for ( int i = 0 ; i < p.n ; i++ ){
if ( i == p.n - 1 )//last term does not have + appended
out << p.terms[i][0] <<"x^"<<p.terms[i][1]<<endl;
else
out << p.terms[i][0]<<"x^"<<p.terms[i][1]<<" + ";
}
return out;
}
Polynomial :: Polynomial(){
for ( int i = 0; i < MAX; i++ ){
terms[i][0] = 0;
terms[i][1] = 0;
}
}
void Polynomial :: enterTerms(){//enterTerms() not in constructor so that no prompt for entering
//terms while doing + - etc., they also produce Poylnomial instance (i.e. invoke constructor)
int num;
cout<<"enter number of terms in polynomial\n";
cin >> num;
n = num >= 0 ? num : 1;
cout << "enter coefficient followed by exponent for each term in polynomial\n";
for ( int i = 0; i < n ; i++)
cin >> terms[i][0] >> terms[i][1] ;
}
Polynomial Polynomial :: operator + ( const Polynomial & p ){
Polynomial temp, sum;
temp.n = n + p.n;
int common = 0;
// first write sum as concatenation of p1 and p2
for ( int i = 0 ; i < n ; i++ ){
temp.terms[i][0] = terms[i][0];
temp.terms[i][1] = terms[i][1];
}
//notice j and k for traversing second half of sum, and whole p2 resp
for ( int j = n, k = 0; j < n + p.n, k < p.n ; j++, k++ ){
temp.terms[j][0] = p.terms[k][0];
temp.terms[j][1] = p.terms[k][1];
}
for ( int l = 0; l < temp.n - 1 ; l++ ){ // 0 to 1 less than length
for ( int m = l + 1 ; m < temp.n ; m++ ){ // 1 more than l to length,so that compared pairs are non redundant
if( temp.terms[l][1] == temp.terms[m][1] ){
common++; //common terms reduce no. of terms in sum (see sum.n decl)
temp.terms[l][0] += temp.terms[m][0]; //coefficients added if exponents same
temp.terms[m][0] = 0;
}
}
}
sum.n = temp.n - common; //if you place it above, common taken as 0 and sum.n is same as temp.n (logical error)
//just to debug, print temporary array
cout << endl << temp;
for ( int q = 0, r = 0; q < temp.n; q++ ){
if ( temp.terms[q][0] == 0 )
continue;
else{
sum.terms[r][0] = temp.terms[q][0];
sum.terms[r][1] = temp.terms[q][1];
r++;
}
}
cout << endl << sum;
return sum;
}
int Polynomial :: evaluate(Polynomial p, int x)
{
Polynomial terms;
return 0;
}
int main()
{
Polynomial p1 , p2;
p1.enterTerms();
p2.enterTerms();
cout << "Please enter the value of x:" << endl;
cin >> x;
//evaluate(p1);
//evaluate(p2);
p1 + p2;
system("PAUSE");
//cin.get();
return 1;
}
Please consider a simpler data structure. A common approach is to use a single array, where the index is the power of x. Just use zeros where no such term exists. Then x^3 + 2*x + 1 is written {1, 2, 0, 1}, since there's no x^2. Also note the reverse order, since p[0] represents x^0. This drastically simplifies operations like addition.
As far as evaluation, just think about the equation. If your polynomial is x^2 + 3*x + 5, and you want to evaluate for x=7, what do you do? Start with power 0, and accumulate each term into a single variable.
You can follow and complete my functions here:
float polyval_point(Eigen::VectorXf v,float x)
{
float s = 0;
for (int i=0;i<v.size();i++)
{
s += v[i] * pow(x,i);
}
return s;
}
Eigen::VectorXf polyval_vector(Eigen::VectorXf v,Eigen::VectorXf X)
{
Eigen::VectorXf S(X.size());
for (int i=0;i<X.size();i++)
{
S[i] = polyval_point(v,X[i]);
}
return S;
}
I'm practicing ACM problems to become a better programmer, but I'm still fairly new to c++ and I'm having trouble interpreting some of the judges code I'm reading. The beginning of a class starts with
public:
State(int n) : _n(n), _p(2*n+1)
{
and then later it's initialized with
State s(n);
s(0,0) = 1;
I'm trying to read the code but I can't make sense of that. The State class only seems to have 1 argument passed, but the programmer is passing 2 in his initialization. Also, what exactly is being set = to 1? As far as I can tell, the = operator isn't being overloaded but just in case I missed something I've included the full code below.
Any help would be greatly appreciated.
Thanks in advance
/*
* D - Maximum Random Walk solution
* ICPC 2012 Greater NY Regional
* Solution by Adam Florence
* Problem by Adam Florence
*/
#include <cstdio> // for printf
#include <cstdlib> // for exit
#include <algorithm> // for max
#include <iostream>
#include <vector>
using namespace std;
class State
{
public:
State(int n) : _n(n), _p(2*n+1)
{
if (n < 1)
{
cout << "Ctor error, n = " << n << endl;
exit(1);
}
for (int i = -n; i <= n; ++i)
_p.at(i+_n) = vector<double>(n+1, 0.0);
}
void zero(const int n)
{
for (int i = -n; i < n; ++i)
for (int m = 0; m <= n; ++m)
_p[i+_n][m] = 0;
}
double operator()(int i, int m) const
{
#ifdef DEBUG
if ((i < -_n) || (i > _n))
{
cout << "Out of range error, i = " << i << ", n = " << _n << endl;
exit(1);
}
if ((m < 0) || (m > _n))
{
cout << "Out of range error, m = " << m << ", n = " << _n << endl;
exit(1);
}
#endif
return _p[i+_n][m];
}
double& operator()(int i, int m)
{
#ifdef DEBUG
if ((i < -_n) || (i > _n))
{
cout << "Out of range error, i = " << i << ", n = " << _n << endl;
exit(1);
}
if ((m < 0) || (m > _n))
{
cout << "Out of range error, m = " << m << ", n = " << _n << endl;
exit(1);
}
#endif
return _p[i+_n][m];
}
static int min(int x, int y)
{
return(x < y ? x : y);
}
static int max(int x, int y)
{
return(x > y ? x : y);
}
private:
int _n;
// First index is the current position, from -n to n.
// Second index is the maximum position so far, from 0 to n.
// Value is probability.
vector< vector<double> > _p;
};
void go(int ds)
{
// Read n, l, r
int n, nds;
double l, r;
cin >> nds >> n >> l >> r;
const double c = 1 - l - r;
if(nds != ds){
cout << "Dataset number " << nds << " does not match " << ds << endl;
return;
}
// Initialize state, probability 1 at (0,0)
State s(n);
s(0,0) = 1;
State t(n);
State* p1 = &s;
State* p2 = &t;
for (int k = 1; k <= n; ++k)
{
// Compute probabilities at step k
p2->zero(k);
// At step k, the farthest from the origin you can be is k
for (int i = -k; i <= k; ++i)
{
const int mm = State::min( State::max(0, i+k), k);
for (int m = 0; m <= mm; ++m)
{
// At step k-1, p = probability of (i,m)
const double p = p1->operator()(i,m);
if (p > 0)
{
// Step left
p2->operator()(i-1, m) += p*l;
// Step right
p2->operator()(i+1, State::max(i+1,m)) += p*r;
// Stay put
p2->operator()(i, m) += p*c;
}
}
}
swap(p1, p2);
}
// Compute expected maximum position
double p = 0;
for (int i = -n; i <= n; ++i)
for (int m = 0; m <= n; ++m)
p += m * p1->operator()(i,m);
printf("%d %0.4f\n", ds, p);
}
int main(int argc, char* argv[])
{
// Read number of data sets to process
int num;
cin >> num;
// Process each data set identically
for (int i = 1; i <= num; ++i)
go(i);
// We're done
return 0;
}
You are confusing a call to state::operator()(int, int) with an initialization. That operator call lets you set the value of an element of the class instance.
State s(n); // this is the only initialization
s(0,0) = 1; // this calls operator()(int, int) on instance s
In this line:
s(0,0) = 1;
it's calling this:
double& operator()(int i, int m)
and because it returns a reference to a double, you can assign to it.
The second line is no longer initialization. The constructor was invoked in line 1, the second line invokes
double& operator()(int i, int m)
with n=0 and m=0 and writing 1 to the reference that is returned.
This part:
State(int n) : _n(n), _p(2*n+1)
...is a member initializer list. It's sort of similar to if you'd written the construct like:
state(int n) { _n = n; _p = 2*n+1; }
...except that it initializes _n and _p instead of starting with them unitialized, then assigning values to them. In this specific case that may not make much difference, but when you have things like references that can only be initialized (not assigned) it becomes crucial.
The s(0,0) = 1 looks like s is intended to act a little like a 2D array, and they've overloaded operator() to act as a subscripting operator for that array. I posted a class that does that in a previous answer.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am trying to write a program that constructs a polynomial from an input file. It reads in the polynomial and stores values into the class attributes "coefficient" and "exponent". E.g. coefficient = 2, exponent = 3 would result in 2x^3. There are a lot of annoying corner cases that must be handled when reading in the polynomial and outputting. (operator<< and operator>> functions) My main function thoroughly tests my polynomial.cpp. I believe one of my problems is coming from constructing the polynomial and as you may note, I'm also having trouble writing code for my derive function. Here is what I have:
#ifndef _POLYNOMIAL_H
#define _POLYNOMIAL_H
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
class Polynomial {
public:
Polynomial();
Polynomial(vector<double> iCoefficients, vector<int> iExponents);
int Degree() const;
double Evaluate(double x) const;
Polynomial Derivative() const;
friend Polynomial operator+(const Polynomial & p, const Polynomial & p2);
friend Polynomial operator*(const Polynomial & p, const Polynomial & p2);
friend ostream& operator<<(ostream& out, const Polynomial & p);
friend istream& operator>>(istream& in, Polynomial & p);
private:
vector<double> coefficients;
};
#endif
#include "polynomial.h"
#include <stdexcept>
#include <vector>
#include <cmath>
using namespace std;
// Default Constructor
Polynomial::Polynomial() {
coefficients.push_back(0);
}
// Constructor for a Polynomial
Polynomial::Polynomial(vector<double> iCoefficients, vector<int> iExponents) {
for (int i = 0; i < iExponents[0]; i++) {
coefficients.push_back(0);
}
for (size_t i = 0; i < iExponents.size(); i++) {
coefficients[(Degree() - iExponents[i])] = iCoefficients[i];
}
}
// Returns highest exponent of the polynomial
int Polynomial::Degree() const {
return coefficients.size();
}
// Evaluates the polynomial at a particular point
double Polynomial::Evaluate(double x) const {
double result;
for(int i = 0; i <= Degree(); i++) {
result += pow(x, Degree() - i) * coefficients[i];
}
return result;
}
// Returns first derivative of the polynomial
Polynomial Polynomial::Derivative() const { //----------------------???
// Polynomial result;
// for(int i = 0; i <= Degree(); i++) {
// result.coefficients[i] = coefficients[i] * (Degree() - i);
// }
// return result;
}
// Returns polynomial object that is the sum of parameters
Polynomial operator+(const Polynomial & p, const Polynomial & p2) {
int d = p.Degree();
int d2 = p2.Degree();
Polynomial sum;
for (int j = 0; j < d; j++) {
for (int i = 0; i < d2; i ++) {
sum.coefficients.push_back(p.coefficients[j] + p2.coefficients[i]);
}
}
return sum;
}
// Returns polynomial object that is the product of parameters
Polynomial operator*(const Polynomial & p, const Polynomial & p2) {
int d = p.Degree();
int d2 = p2.Degree();
Polynomial product;
for (int j = 0; j < d; j++) {
for (int i = 0; i < d2; i ++) {
product.coefficients.push_back(p.coefficients[j] * p2.coefficients[i]);
}
}
return product;
}
// Output operator
ostream& operator<<(ostream& out, const Polynomial & p) {
for (int i = 0; i <= p.Degree(); i++) {
if(i == 0 && p.Degree() <= 1) {
out << 0;
}
if (p.coefficients[i] != 0 && i != 0) {
out << '+';
}
if (p.coefficients[i] != 0) {
out << p.coefficients[i];
if(i < (p.Degree() - 1)) {
out << "x^";
out << (i - p.Degree()) * (-1);
}
}
}
return out;
}
// Input operator
istream& operator>>(istream& in, Polynomial & p) {
char ch;
int exponent;
double coefficient;
vector<double> coefficients;
vector<int> exponents;
while(isspace(ch) == false) {
ch = in.peek();
if(ch == '+') {
in.ignore();
in >> coefficient;
}
else if(ch == '-') {
in.ignore();
in >> coefficient;
coefficient = coefficient * (-1);
}
else {
in >> coefficient;
}
ch = in.peek();
if((ch <= 'z') && (ch >= 'a')) {
in >> ch;
ch = in.peek();
if(ch == '^') {
in.ignore();
in >> exponent;
}
else
exponent = 1;
}
else
exponent = 0;
coefficients.push_back(coefficient);
exponents.push_back(exponent);
}
p = Polynomial(coefficients, exponents);
return in;
}
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
#include "polynomial.h"
using namespace std;
bool testPolynomial(const Polynomial& p, string expected);
bool testOperations(const Polynomial& p, int degree, double expected);
bool testInput(string s);
int main() {
int errors = 0;
cerr << "Note: Nearly all of the tests expect a working output operator. If a test fails, check that first" << endl;
cerr << "Testing default constructor" << endl;
Polynomial p1; // test default constructor
errors += testPolynomial(p1, "0");
cerr << "Testing explicit value constructor" << endl;
double c_arr[] = {1.1, 2, 4, 7};
int e_arr[] = {6, 3, 2, 0};
vector<double> c(c_arr, c_arr+4);
vector<int> e(e_arr, e_arr+4);
Polynomial p2(c, e);
errors += testPolynomial(p2, "1.1x^6+2x^3+4x^2+7");
c.clear(); e.clear();
cout << '1' << endl;
Polynomial p3(c, e);
errors += testPolynomial(p3, "0");
cout << '2' << endl;
cerr << "Testing operations" << endl;
double c2_arr[] = {-1.1, 2, -4, 7};
int e2_arr[] = {4, 3, 2, 0};
vector<double> c2(c2_arr, c2_arr+4);
vector<int> e2(e2_arr, e2_arr+4);
Polynomial p4(c2,e2);
errors += testOperations(p1, 0, 0);
errors += testOperations(p2, 6, 109.4);
errors += testOperations(p4, 4, -10.6);
errors += testPolynomial(p1.Derivative(), "0");
errors += testPolynomial(p2.Derivative(), "6.6x^5+6x^2+8x");
errors += testPolynomial(p4.Derivative(), "-4.4x^3+6x^2-8x");
errors += testPolynomial(p1+p2, "1.1x^6+2x^3+4x^2+7");
errors += testPolynomial(p2+p4, "1.1x^6-1.1x^4+4x^3+14");
errors += testPolynomial(p1*p2, "0");
errors += testPolynomial(p2*p2, "1.21x^12+4.4x^9+8.8x^8+19.4x^6+16x^5+16x^4+28x^3+56x^2+49");
double c_arr3[] = {-1};
int e_arr3[] = {0};
vector<double> c3 = vector<double>(c_arr3, c_arr3+1);
vector<int> e3 = vector<int>(e_arr3, e_arr3+1);
Polynomial p5(c3, e3);
errors += testPolynomial(p2 * p5 + p2, "0");
errors += testPolynomial(p5, "-1");
cerr << "Testing input operator." << endl;
testInput("0");
testInput("51");
testInput("-1.1");
testInput("3x^2");
testInput("-5x^3-5");
testInput("x^5+x-1");
testInput("-x^4+2");
return errors;
}
bool testPolynomial(const Polynomial& p, string expected) {
ostringstream out;
out << p;
if (out.str() != expected) {
cerr << "Test failed: expected " << expected << " got " << out.str() << endl;
return true;
} else {
return false;
}
}
bool testOperations(const Polynomial& p, int degree, double expected) {
if(p.Degree() != degree) {
cerr << "Failed Degree operation" << endl;
return true;
}
double result = p.Evaluate(2.0);
if (fabs(result - expected) > 1e-5) {
cerr << "Failed Evaluation operation" << endl;
}
return false;
}
bool testInput(string s) {
Polynomial p;
istringstream in(s+" ");
in >> p;
ostringstream out;
out << p;
if (out.str() != s) {
cerr << "Failed input test. Expected: " << s << " got " << out.str() << endl;
return true;
}
return false;
}
The Polynomial::Degree() function has an off-by-one bug; it should return size()-1
In order to convert the lists of coefficients and exponents, first find the maximal exponent; this will be the degree of the polynomial:
int degree = *std::max_element(iExponents.begin(), iExponents.end());
Then, initialize coefficients with this number of zeros (plus one, see above):
coefficients.assign(degree + 1, 0);
Then, set each coefficient, just like you did.
However, it is much better to use ascending order of powers/exponents! This way, you don't need to calculate Degree()-i all the time, you can use i instead.
for (size_t i = 0; i < iExponents.size(); i++) {
coefficients[iExponents[i]] += iCoefficients[i];
}
Note += in the code above; it handles polynomials like 3x+4x+5x, making that equivalent to 12x.
Your addition and multiplication algorithms are completely wrong. You should first set the degree of the output polynomial, just like you did in the constructor:
Polynomial operator+(const Polynomial & p, const Polynomial & p2)
{
int d = p.Degree();
int d2 = p2.Degree();
Polynomial sum;
sum.coefficients.assign(std::max(d, d2) + 1, 0);
...
}
The rest should be easier, once you try to think about it.
After performing the addition, you might want to check for zero highest-degree coefficients; for example, when you add 2x^2+x+1 and -2x^2+x+1, you get 0x^2+2x+2, which you might want to convert to 2x+2:
while (coefficients.back() == 0)
coefficients.resize(coefficients.size() - 1);
if (coefficients.empty())
coefficients.push_back(0);
Derivative should be easy, once you get operator+ and operator* right.