I'm working on a polynomial class that basically does +,-,*,/, and evaluates polynomials. I keep running into bugs (specifically output is incorrect) and I think it's because of one of my operation methods (maybe addition??).
EDIT: Narrowed down problem to +() operator. It cannot add polynomials and a double.
Any help would be appreciated, please!
Polynomial Class CPP:
#include <iostream>
#include "polynomial.h"
using namespace std;
/*
=======================
Constructors
=======================
*/
Polynomial::Polynomial() //default constructor
{
for ( int i = 0; i < 20; i++ )
{
coefs[i] = 0;
}
}
Polynomial::~Polynomial() {}
void Polynomial::set(int coef, int pwr){
coefs[pwr] = coef;
pwrs = degree();
}
int Polynomial::degree()
{
int d = 0;
for ( int i = 0; i < 20; i++ )
if ( coefs[i] != 0 ) d = i;
return d;
}
/*
=======================
operator=
=======================
*/
Polynomial& Polynomial::operator= ( const Polynomial& poly )
{
if ( this == &poly ) return ( *this ) ;
else{
for (int i = 0; i < 20; i++)
coefs[i] = poly.coefs[i];
}
return ( *this );
}
/*
=======================
operator+
=======================
*/
Polynomial operator+(const Polynomial& a, const Polynomial& b )
{
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ ) c.coefs[i] += a.coefs[i];
for ( int i = 0; i <= b.pwrs; i++ ) c.coefs[i] += b.coefs[i];
c.pwrs = c.degree();
return c;
}
Polynomial operator+(const Polynomial& a, const double& d)
{
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ ){
if(i == a.pwrs) {
i=i+1;
c.coefs[i] = d;
}
c.coefs[i] += a.coefs[i];
}
c.pwrs = c.degree();
return c;
}
/*
=======================
Operator-
=======================
*/
Polynomial operator- (const Polynomial& a,const Polynomial& b )
{
//Polynomial a = *this; //a is the poly on the L.H.S
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ ) c.coefs[i] += a.coefs[i];
for ( int i = 0; i <= b.pwrs; i++ ) c.coefs[i] -= b.coefs[i];
c.pwrs = c.degree();
return c;
}
/*
=======================
Operator*
=======================
*/
Polynomial operator* (const Polynomial& a, const Polynomial& b)
{
//Polynomial a = *this; //a is the poly on the L.H.S
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ )
for ( int j = 0; j <= b.pwrs; j++ )
c.coefs[i+j] += ( a.coefs[i] * b.coefs[j] );
c.pwrs = c.degree();
return c;
}
Polynomial operator*(const Polynomial& poly1, const double& d)
{
Polynomial poly;
for(int i = 0; i < 20; i++)
poly.coefs[i] = poly1.coefs[i] * d;
poly.pwrs = poly1.pwrs;
return poly;
}
Polynomial operator*(const double& d, const Polynomial& poly1)
{
Polynomial poly;
for(int i = 0; i < 20; i++)
poly.coefs[i] = d * poly1.coefs[i];
poly.pwrs = poly1.pwrs;
return poly;
}
/*
=======================
Operator/
=======================
*/
Polynomial operator/ (const Polynomial& a, const Polynomial& b)
{
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ )
for ( int j = 0; j <= b.pwrs; j++ )
c.coefs[i+j] += ( a.coefs[i] / b.coefs[j] );
c.pwrs = c.degree();
return c;
}
ostream& operator<<(ostream& out, const Polynomial& p) {
for ( int i = 19; i >= 0; i-- ) {
if(p.pwrs > 1){
if ( p.coefs[i] != 0 ) {
cout << p.coefs[i] << "x^" << i << " ";
if(p.coefs[i-1] > 0)
cout << "+";
else if(p.coefs[i-1] < 0)
cout << "";
}
}
else if (p.pwrs == 1)
cout << p.coefs[i] << "x ";
else if(p.pwrs == 0)
cout << p.coefs[i];
}
cout << endl;
}
Main:
#include <iostream>
#include "polynomial.h"
#include "monomial.h"
using namespace std;
int main(){
Polynomial a, b, c, d, e,result;
a.set(1,3); //x^3
b.set(1,2); //x^2
c.set(6,1); //6x
d.set(0.01,10); //(1/100)x^10
e.set(2,5); //2x^5
result = 4*(a+b)*(c+1)*(d-e); // 4 * (x^3+x^2) * (6x+1) * ((1/100)x^10 - 2x^5)
}
You probably need to set pwrs = degree(); in operator =.
Also, as #6502 pointed out, your operator + is incorrect. You could change it like this:
Polynomial operator+(const Polynomial& a, const double& d)
{
Polynomial c;
c.coefs[0] = d;
for ( int i = 0; i <= a.pwrs; i++ ){
c.coefs[i] += a.coefs[i];
}
c.pwrs = c.degree();
return c;
}
Still inefficient, but at least it should give the correct result.
There is a logic problem with addition of a double. In that case you only want to add to coefs[0], not to all of them.
Why are you defining an assignment operator? Isn't the default one correct for this class?
Besides the problem that Henrink pointed out, assigning 0.01 to coef is meaningless. As only int is accepted here.
void Polynomial::set(int coef, int pwr){
coefs[pwr] = coef;
pwrs = degree();
}
Related
This is a project for my object oriented programming class. I need to introduce the followings: overloading + to sum two polynomials, overloading * to multiply a polynomial with a scalar or to multiply it with another polynomial, overloading [] to return coeficient on a specific position, method for adding , deleting a coeficient and evaluating polynom in a certain point (f(x)).
1.Everything is working besides the destructor. The destructor that should be used (delete [] coef) of Polynomial will break (Heap Coruption) if i use cout << A + B and i do not know why.
What i use right now is a workaround but it will not delete coef[0]. That's the point where it breaks. If you can help me somehow i will be gratefull. Can you understand what caused it?
2.I need to have one more overloaded operator, " / ". It should make division between two polynomials and I do not know how to implement it. I tried to search for it but i couldn't understand any algorithm. Any advice or algorithm explanation would be great, because i really do not know from where to start and i need to finish it until tommorrow morning.
3.If you have any advice on coding or efficienty will also be great ( project requirement: do not use STL ).
Thank you!
Polynomial.h:
#pragma once
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
using std::istream;
class Polynomial
{
unsigned int deg;
double *coef;
public:
Polynomial() : deg(1), coef(new double[1]) {}
Polynomial(double [], int);
Polynomial(Polynomial&);
Polynomial& operator = (const Polynomial&);
~Polynomial();
friend ostream &operator <<(ostream&, const Polynomial&);
friend istream &operator >>(istream&, Polynomial&);
Polynomial operator + (const Polynomial) ;
double operator[] (unsigned int) const;
Polynomial operator * (int) const;
Polynomial operator * (const Polynomial obj) const;
unsigned int getDeg() { return this->deg; };
double eval(int);
void addCoef(double, int);
void delCoef(int);
};
inline Polynomial::Polynomial(double coefficients[], int number) : deg(number), coef(new double[number])
{
for (int i = 0; i < deg; i++) {
coef[i] = coefficients[i];
}
}
inline Polynomial::Polynomial(Polynomial &ob) {
this->deg = ob.deg;
this->coef = new double[deg];
for (int i = 0; i <= deg; i++)
{
this->coef[i] = ob.coef[i];
}
}
inline Polynomial::~Polynomial() {
for (int i = this->deg; i > 0; i--)
this->delCoef(i);
this->coef[0] = 0; //If i write it like this delete [] coef; it breaks.
this->deg = 0; //with HeapCoruption detected
}
Polynomial.cpp:
Polynomial& Polynomial::operator = (const Polynomial& obj)
{
if (this != &obj) //Testing to avoid situations like A = A;
{
this->deg = obj.deg;
for (int i = 0; i <= obj.deg; i++)
this->coef[i] = obj.coef[i];
}
return *this;
}
istream& operator >> (istream& in, Polynomial& obj)
{
in >> obj.deg;
cout << endl;
obj.coef = new double[obj.deg];
for (int i = 0; i <= obj.deg; i++)
{
in >> obj.coef[i];
}
return in;
}
ostream& operator << (ostream& out, const Polynomial& obj)
{
out << obj.deg << endl;
for (int i = 0; i <= obj.deg; i++)
{
if (obj.coef[i] != 0)
{
if (obj.coef[i] < 0)
out << '(' << obj.coef[i] << ')';
else
out << obj.coef[i];
if (i > 1)
out << "*x^" << i;
if (i == 1)
out << "*x";
if (i != obj.deg)
out << " + ";
}
}
out << endl <<endl;
return out;
}
Polynomial Polynomial::operator+ (const Polynomial obj)
{
Polynomial aux;
if (obj.deg >= deg)
{
aux.deg = obj.deg;
aux.coef = new double[obj.deg];
for (int i = 0; i <= deg; i++)
aux.coef[i] = obj.coef[i] + coef[i];
for (int i = deg + 1; i <= obj.deg; i++)
aux.coef[i] = obj.coef[i];
}
else // obj.deg < this->deg
{
aux.deg = deg;
aux.coef = new double[deg];
for (int i = 0; i <= obj.deg; i++)
{
aux.coef[i] = obj.coef[i] + coef[i];
}
for (int i = obj.deg + 1; i <= deg; i++)
{
aux.coef[i] = coef[i];
}
}
return aux;
}
double Polynomial::operator[] (unsigned int pos) const
{
if (pos > this->deg) {
throw std::out_of_range("Index bigger than polynomial length");
}
return this->coef[pos];
}
Polynomial Polynomial::operator * (const int scalar) const
{
Polynomial aux;
aux.deg = this->deg;
aux.coef = new double[aux.deg];
for (int i = 0; i <= aux.deg; i++)
aux.coef[i] = this->coef[i] * scalar;
return aux;
}
Polynomial Polynomial::operator * (const Polynomial obj) const
{
Polynomial aux;
aux.deg = obj.deg + this->deg;
aux.coef = new double[aux.getDeg()];
for (int i = 0; i <= aux.getDeg(); i++)
aux.addCoef(0, i);
for (int i = 0; i <= this->deg; i++)
for (int j = 0; j <= obj.deg; j++)
aux.coef[i+j] += (this->coef[i]) * obj.coef[j];
return aux;
}
double Polynomial::eval(int x) {
double sum = 0;
for (int i = 0; i <= this->deg; i++)
{
if (i == 0)
sum += this->coef[0];
else
{
int aux = i;
int xaux = x;
aux--;
while (aux != 0)
{
xaux *= x;
aux--;
}
sum += this->coef[i] * xaux;
}
}
return sum;
}
void Polynomial::addCoef(double NewCoef, int pos)
{
if (pos < 0)
return;
if (pos > this->deg)
{
double *newCoef = new double[pos];
for (int i = 0; i <= this->deg; i++)
newCoef[i] = this->coef[i];
for (int i = this->deg + 1; i < pos; i++)
newCoef[i] = 0;
newCoef[pos] = NewCoef;
this->coef = newCoef;
this->deg = pos;
return;
}
else
{
this->coef[pos] = NewCoef;
}
}
void Polynomial::delCoef(int pos)
{
if (pos > this->deg || pos < 0 )
return;
if (pos == this->deg)
{
this->coef[pos] = 0;
int degNoua = pos - 1;
while (this->coef[pos] == 0 && pos != 0)
pos--;
if (pos == 0 && this->coef[pos] == 0)
{
delete this->coef;
this->deg = 0;
}
else
{
this->deg = pos;
double *aux = new double[pos];
for (int i = 0; i <= pos; i++)
aux[i] = this->coef[i];
this->coef = aux;
}
}
else
{
this->coef[pos] = 0;
}
}
This question already has answers here:
calling destructor explicitly
(2 answers)
Closed 3 years ago.
So I have a class Vector and when I'm calling in main for example the destructor of an object I get an exception. The line of code from the exception file is "free_dbg(block, _UNKNOWN_BLOCK)"; Note that if I do only the reading of the vectors or only the destructor call, I won't get the exception. When I do both together, this is when the problem appears.
Here is the code:
#include "pch.h"
#include <iostream>
#include <fstream>
using namespace std;
class Vector
{
public:
Vector();
~Vector();
Vector(const Vector& vec);
void insert_element(int value, int position);
void delete_element(int position);
void set_nr_elem(int nr) { nr_elem = nr; }
int get_nr_elem() const { return nr_elem; }
int get_element(int position) const { return arr[position]; }
friend istream& operator>>(istream& input, Vector &vec);
friend ostream& operator<<(ostream& output, const Vector &vec);
Vector operator=(const Vector& vec);
void free_memory() { delete[] arr; }
private:
int *arr;
int nr_elem;
};
Vector::Vector()
{
arr = NULL;
nr_elem = 0;
}
Vector::~Vector()
{
delete[]arr;
nr_elem = 0;
}
Vector::Vector(const Vector& vec)
{
arr = new int[vec.nr_elem];
nr_elem = vec.nr_elem;
for (int i = 0; i < nr_elem; i++)
arr[i] = vec.arr[i];
}
void Vector::insert_element(int value, int position)
{
if (position < 0 || position > nr_elem)
{
cout << "Invalid position";
return;
}
arr = (int*)realloc(arr, (nr_elem + 1) * sizeof(int));
for (int i = nr_elem; i >= position + 1; i--)
arr[i] = arr[i - 1];
arr[position] = value;
nr_elem++;
}
void Vector::delete_element(int position)
{
if (position < 0 || position >= nr_elem)
{
cout << "Invalid position";
return;
}
for (int i = position; i < nr_elem; i++)
arr[i] = arr[i + 1];
delete &arr[nr_elem];
nr_elem--;
}
istream& operator>>(istream& input, Vector &vec)
{
int nr;
input >> nr;
for (int i = 0; i < nr; i++)
{
int x;
input >> x;
vec.insert_element(x, vec.get_nr_elem());
}
return input;
}
ostream& operator<<(ostream& output, const Vector &vec)
{
if (vec.get_nr_elem())
{
output << "Number of elements: " << vec.get_nr_elem() << "\n";
output << "The elements: ";
for (int i = 0; i < vec.get_nr_elem(); i++)
output << vec.get_element(i) << " ";
output << "\n";
}
else
{
output << "The vector has no elements";
}
return output;
}
Vector Vector::operator=(const Vector& vec)
{
if (this == &vec)
return *this;
delete[] arr;
arr = new int[vec.nr_elem];
for (int i = 0; i < vec.nr_elem; i++)
arr[i] = vec.arr[i];
nr_elem = vec.nr_elem;
return *this;
}
class Natural_Big_Number
{
public:
void set_sign(char c) { sign = c; }
char get_sign() const { return sign; }
friend istream& operator>>(istream& input, Natural_Big_Number &number);
friend ostream& operator<<(ostream& output, const Natural_Big_Number &number);
friend Natural_Big_Number operator+(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
friend Natural_Big_Number operator-(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
friend Natural_Big_Number& operator*(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
friend Natural_Big_Number& operator/(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
Natural_Big_Number operator=(const Natural_Big_Number& number);
private:
Vector vec;
char sign;
};
istream& operator>>(istream& input, Natural_Big_Number &number)
{
int x;
input >> x;
char c;
input.get();
c = input.get();
if (c == '-')
number.set_sign('-');
else
{
number.set_sign('+');
int digit = (int)c - 48;
number.vec.insert_element(digit, number.vec.get_nr_elem());
}
while ((c = input.get()) >= '0' && c <= '9')
{
int digit = (int)c - 48;
number.vec.insert_element(digit, number.vec.get_nr_elem());
}
return input;
}
ostream& operator<<(ostream& output, const Natural_Big_Number &number)
{
cout << "Number of digits: " << number.vec.get_nr_elem() << '\n';
cout << "The number: ";
if (number.get_sign() == '-')
cout << number.get_sign();
for (int i = 0; i < number.vec.get_nr_elem(); i++)
cout << number.vec.get_element(i);
cout << endl;
return output;
}
Natural_Big_Number operator+(const Natural_Big_Number& number1, const Natural_Big_Number& number2)
{
Natural_Big_Number result;
int carry = 0;
int it_digits1 = number1.vec.get_nr_elem() - 1;
int it_digits2 = number2.vec.get_nr_elem() - 1;
if (number1.get_sign() == number2.get_sign())
{
result.set_sign(number1.get_sign());
while (it_digits1 >= 0 && it_digits2 >= 0)
{
int aux = number1.vec.get_element(it_digits1) + number2.vec.get_element(it_digits2) + carry;
int value = aux % 10;
result.vec.insert_element(value, 0);
carry = aux / 10;
it_digits1--;
it_digits2--;
}
for (int i = 0; i <= it_digits1; i++)
{
int aux = number1.vec.get_element(it_digits1) + carry;
int value = aux % 10;
carry = aux / 10;
result.vec.insert_element(value, 0);
}
for (int i = 0; i <= it_digits2; i++)
{
int aux = number2.vec.get_element(it_digits2) + carry;
int value = aux % 10;
carry = aux / 10;
result.vec.insert_element(value, 0);
}
}
/*else if (number1.get_sign() == '-' && number2.get_sign() == '+')
{
result = number1;
result.set_sign('+');
result = number2 + result;
}*/
cout << result;
return result;
}
Natural_Big_Number operator-(const Natural_Big_Number& number1, const Natural_Big_Number& number2)
{
Natural_Big_Number result;
int carry = 0;
int it_digits1 = number1.vec.get_nr_elem() - 1;
int it_digits2 = number2.vec.get_nr_elem() - 1;
while (it_digits1 >= 0 && it_digits2 >= 0)
{
int aux = number1.vec.get_element(it_digits1) - number2.vec.get_element(it_digits2) + carry;
int value = aux % 10;
result.vec.insert_element(value, 0);
carry = aux / 10;
it_digits1--;
it_digits2--;
}
for (int i = 0; i <= it_digits1; i++)
{
int aux = number1.vec.get_element(it_digits1) + carry;
int value = aux % 10;
carry = aux / 10;
result.vec.insert_element(value, 0);
}
for (int i = 0; i <= it_digits2; i++)
{
int aux = number2.vec.get_element(it_digits2) + carry;
int value = aux % 10;
carry = aux / 10;
result.vec.insert_element(value, 0);
}
cout << result;
return result;
}
Natural_Big_Number Natural_Big_Number::operator=(const Natural_Big_Number& number)
{
if (this == &number)
return *this;
vec.free_memory();
set_sign(number.get_sign());
vec = number.vec;
return *this;
}
int main()
{
ifstream f("date.in");
Natural_Big_Number number1, number2;
f >> number1 >> number2;
number1 = number2;
cout << number1;
return 0;
}
That's because you shouldn't do that.
The destructor is called for you when vec1 goes out of scope.
Your program attempts to destroy vec1 twice, which causes mayhem.
I'm making a 2D dynamic Matrix class. Problem arises in my copy constructor and =operator. Kindly tell me what am I doing wrong. Here is the code: (The cout's are for checking.
private:
int rows;
int coloumns;
float **ptr;
Matrix(const Matrix & M)
{ cout << "copy const called"<<endl;
cout << "1 "<< endl;
if(rows < 0 || column < 0) // To check if its a garbage value or not
{
rows = 0, col = 0;
ptr = NULL;
cout << "2 "<< endl;
}
else if(ptr!=NULL)
{
cout << "3 "<< endl;
for(int i = 0 ; i < col; i++)
{
delete [] ptr[i];
}
cout << "4 "<< endl;
delete [] ptr;
ptr = NULL;
cout << "5 "<< endl;
}
cout << "6 "<< endl;
*this = M;
cout << "7 "<< endl;
}
Matrix operator= (const Matrix &M)
{
if(this == &M)
{
return *this;
}
if(row!=0 && columns != 0)
{
for(int i = 0 ; i < columns; i++)
{
delete [] ptr[i];
}
delete [] ptr;
ptr = NULL;
}
rows = M.rows; col = M.columns;
ptr = new float *[rows];
for(int i = 0; i < rows; i++)
{
ptr[i] = new float [col];
}
for(int i = 0; i< rows ; i++)
{
for( int j=0 ; j< columns ;j++)
{
ptr[i][j] = M.ptr[i][j];
}
}
return *this;
}
int main()
{
Matrix M1(2,3);
Matrix M2(M1);
M2(0, 0) = 1;
}
It stops at the " *this = M " in the copy constructor. Moreover, I wanted to confirm that when I return something in the = operator, does it take the place of the whole " *this = M" , or just replaces M?
Note:
Not allowed to use vectors.
You have infinite recursion going on. In you copy constructor you have
*this = M;
This calls your class's operator= which you have declared as
Matrix operator= (const Matrix &M)
You can see that you are returning by value. When you return by value a copy is made. To make that copy we need to call the copy construct. This in turn calls the assignment operator again which call the copy constructor and the cycle just keeps going.
Your copy constructor can be corrected and simplified to be
Matrix(const Matrix & m) : rows(m.rows), columns(m.columns)
{
ptr = new float*[rows];
for (int i = 0; i < rows; i++)
ptr[i] = new float[columns];
for (int i = 0; i < rows; i++)
for (int j = 0; j < columns; j++)
ptr[i][j] = m.ptr[i][j]
}
Notice how I didn't have to check the state of the new class as we know what it is since we are initializing it. Everything is uninitialized and all we have to do is initialize everything and then copy the values from the one matrix into the new one.
In regards to you assignment operator you should have it return a reference to the object instead of returning by value. This avoids unnecessary copies and allows you to chain the operator with other operators.
Your code looks complicated to me.
I do not understand why you have chosen float** instead of plain float*. This looks better to me:
int rc, cc; // row count, column count
float* d; // data (rc * cc floats)
Memory allocation became a simpler operation:
d = new float[ rc * cc ];
Copying is also simpler:
memcpy( d, source.d, rc * cc * sizeof( *d ) );
The "hard" part is to retrieve a matrix element. You have to convert a row and column to an index:
index = row * column_count + column;
The whole class:
#include <iostream>
class matrix_type
{
int rc, cc; // row count, column count
float* d; // data
void allocate( const int arc, const int acc ) // a prefix in arc and acc stands for Argument
{
if ( arc * acc == rc * cc )
return; // nothing to do: already allocated
delete[] d;
rc = arc;
cc = acc;
d = new float[rc * cc];
}
void copy( const matrix_type& s )
{
allocate( s.rc, s.cc );
memcpy( d, s.d, rc * cc * sizeof( *d ) );
}
int as_idx( const int ar, const int ac ) const
{
return ar * cc + ac;
}
public:
matrix_type( const int arc, const int acc ) : rc( 0 ), cc( 0 ), d( 0 )
{
allocate( arc, acc );
memset( d, 0, rc * cc * sizeof( *d ) );
}
matrix_type()
{
delete[] d;
}
matrix_type( const matrix_type& s ) : rc( 0 ), cc( 0 ), d( 0 )
{
copy( s );
}
matrix_type& operator=(const matrix_type& s)
{
copy( s );
return *this;
}
float& at( const int ar, const int ac )
{
if ( ar < rc && ac < cc )
return d[as_idx( ar, ac )];
else
throw "out of range";
}
const float& at( const int ar, const int ac ) const
{
return const_cast<matrix_type*>(this)->at( ar, ac );
}
void print( std::ostream& os ) const
{
for ( int r = 0; r < rc; ++r )
{
for ( int c = 0; c < cc; ++c )
os << at( r, c ) << ' ';
os << '\n';
}
}
};
int main()
{
matrix_type m1( 3, 5 );
m1.at( 0, 0 ) = 1.f;
m1.at( 2, 4 ) = 15.f;
matrix_type m2( m1 );
matrix_type m3( 0, 0 );
m3 = m2;
m3.print( std::cout );
return 0;
}
Here is my code, why is it showing segmentation fault? Can someone correct my mult4 function... I know that problem is mult4 and i am not sure is function mult4 is correct solution for polynomial recursively multiplication...
#include <iostream>
#include <cstdlib>
using namespace std;
class Polynomial
{
public:
Polynomial()
{
deg=0;
coeff = new float[deg+1];
coeff[0]=0;
}
Polynomial(int n)
{
deg = n;
coeff = new float[deg+1];
for(int i = 0; i<=deg;i++)
coeff[i] = rand()/(float)RAND_MAX;
}
Polynomial(float *array, int n)
{
deg=n;
coeff=array;
}
Polynomial(const Polynomial& P)
{
deg = P.deg;
coeff = new float[deg+1];
for(int i=0;i<=deg;i++) coeff[i] = P.coeff[i];
}
~Polynomial()
{
delete []coeff;
}
Polynomial operator+(const Polynomial& P) const;
Polynomial operator-(const Polynomial& P) const
{
int i;
Polynomial c;
if(deg>=P.deg)
{
c.deg=deg;
for(i=deg;i>=0;i--)
c.coeff[i]=coeff[i];
for(i=P.deg;i>=0;i--)
c.coeff[i]=c.coeff[i]-P.coeff[i];
}
else
{
c.deg=P.deg;
for(i=P.deg;i>=0;i--)
c.coeff[i]=-P.coeff[i];
for(i=deg;i>=0;i--)
c.coeff[i]=c.coeff[i]+coeff[i];
}
return c;
}
Polynomial& operator=(const Polynomial& P)
{
if (this!=&P)
{
delete [] coeff;
deg = P.deg;
coeff = new float[deg+1];
for(int i=deg;i>=0;i--) coeff[i] = P.coeff[i];
}
return (*this);
}
float operator[](float x) // evaluation of polynomial
{
float rez=0;
for(int i=deg;i>=0;i--)
rez=rez*x+coeff[i];
return rez;
}
int degree() const
{
return deg;
}
public:
float *coeff; // array- representation of polynomial
int deg; //degree of polynomial
friend ostream& operator<<(ostream &out, const Polynomial& P) //overload operatpr<<
{
for ( int i =P.deg; i >= 0; i-- )
{
out << P.coeff[i] << "x^" << i << " ";
if(i>=1)
{
if(P.coeff[i-1]>0) out<<"+";
}
}
out << endl;
return out;
}
};
Polynomial Polynomial::operator+(const Polynomial& P) const
{
int i;
Polynomial c;
if(deg>=P.deg)
{
c.deg=deg;
for(i=deg;i>=0;i--)
c.coeff[i]=coeff[i];
for(i=P.deg;i>=0;i--)
c.coeff[i]=c.coeff[i]+P.coeff[i];
}
else
{
c.deg=P.deg;
for(i=P.deg;i>=0;i--)
c.coeff[i]=P.coeff[i];
for(i=deg;i>=0;i--)
c.coeff[i]=c.coeff[i]+coeff[i];
}
return c;
}
Polynomial shift(Polynomial A, int x)
{
Polynomial c(A.deg+x);
int k=0;
for(int i=c.deg;i>=0;i--)
c.coeff[i]=0;
for(int i=A.deg;i>=0;i--)
{
c.coeff[c.deg-k]=A.coeff[i];
k++;
}
return c;
}
Polynomial mult4( Polynomial P, Polynomial Q)
{
if(P.deg==1)
{
Polynomial qw(2);
qw.coeff[0]=P.coeff[0]*Q.coeff[0];
qw.coeff[2]=P.coeff[1]*Q.coeff[1];
qw.coeff[1]=P.coeff[1]*Q.coeff[0]+Q.coeff[1]*P.coeff[0];
return qw;
}
else
{
Polynomial p1(((P.deg)/2)-1);
Polynomial p2(P.deg-(P.deg)/2);
Polynomial q1(((Q.deg)/2)-1);
Polynomial q2(Q.deg-(Q.deg)/2);
int k=0;
for(int i=p1.deg;i>=0;i--)
{
p1.coeff[i]=P.coeff[i];
}
for(int i=p2.deg;i>=0;i--)
{
p2.coeff[i]=P.coeff[P.deg-k];
k++;
}
for(int i=q1.deg;i>=0;i--)
{
q1.coeff[i]=Q.coeff[i];
}
k=0;
for(int i=q2.deg;i>=0;i--)
{
q2.coeff[i]=Q.coeff[P.deg-k];
k++;
}
Polynomial t1,t2,t3;
t1=mult4(p1+p2,q1+q2);
t2=mult4(p1,q1);
t3=mult4(p2,q2);
return(t2+shift(t1-t2-t3,P.deg/2)+shift(t3,2*(P.deg/2)));
}
}
int main()
{
float *p=new float[4];
for(int i=3;i>=0;i--)
p[i]=-1.1+i;
float *k=new float[5];
for(int i=4;i>=0;i--)
k[i]=-1.2+i;
Polynomial P(p,3);
Polynomial K(k,4);
cout<<mult4(P,K);
return 0;
}
You have several errors in your code.
You need a copy constructor. Familiarize yourself with The Rule Of Three.
There are many lines where you set the deg of a Polynomial but don't allocate memory for coeff. For example, in shift, you have:
Polynomial shift(Polynomial A, float x)
{
Polynomial c;
int k=0;
c.deg=A.deg+x;
for(int i=c.deg;i>=0;i--)
c.coeff[i]=0;
What you need is:
Polynomial shift(Polynomial A, float x)
{
// Polynomial c(A.deg+x);
// Not sure why you whether c.deg should be A.deg+x or just A.deg.
Polynomial c(A.deg);
int k=0;
for(int i=c.deg;i>=0;i--)
c.coeff[i]=0;
In the operator= function, you are changing the index incorrectly. In stead of using:
for(int i=deg;i>=0;i++) coeff[i] = P.coeff[i];
you need to use:
for(int i=deg;i>=0;i--) coeff[i] = P.coeff[i];
// ^^ Decrement, not increment
In mult4, your use of
p1.deg=((P.deg)/2)-1;
seems flawed. What happens when P.deg/2 is equal to 0? Perhaps you need to use:
p1.deg=(P.deg)/2;
Setting of q1.deg must be similarly updated.
I might have missed other errors.
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.