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.
Related
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 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 am trying to run the following code on c++ but keep geting error. Can anyone solve it for me please.
the error message from c++ says:
Error 6 error C2679: binary '<<' : no operator found which takes a
right-hand operand of type 'MVector'
#include <iostream>
#include <cmath>
#ifndef MVECTOR_H // the 'include guard'
#define MVECTOR_H // see C++ Primer Sec. 2.9.2
#include <vector>
#include <string>
#include <fstream>
class MVector
{
public:
// constructors
MVector() {}
explicit MVector(int n) : v(n) {}
MVector(int n, double x) : v(n, x) {}
void push_back(double x)
{
v.push_back(x);
}
double AV()
{
double sum = 0.0, average = 0.0;
for (double i = 0; i<v.size(); i++)
{
sum += v[i];
}
average = sum / v.size();
return average;
}
MVector RunningAverage(int m, int p)
{
MVector movingaverage(v.size() - m - p - 1);
for (int i = m; i < v.size() - p; i++)
{
double sum = 0.0;
if ((i + p < v.size()))
{
for (int j = i - m; j <= i + p; j++)
{
sum += v[j];
movingaverage[i - m] = sum / (m + p + 1);
}
}
}
return movingaverage; // Edit by jpo38
}
// access element (lvalue)
double &operator[](int index) { return v[index]; }
// access element (rvalue)
double operator[](int index) const { return v[index]; }
int size() const { return v.size(); } // number of elements
private:
std::vector<double> v;
};
#endif
int main()
{
using namespace std;
// create an MVector
MVector x;
// add elements to the vector
x.push_back(1.3);
x.push_back(3.5);
x.push_back(3.0);
x.push_back(2.0);
// x now contains 1.3 and 3.5
// print x
std::cout << " x:= ( ";
for (int i = 0; i < x.size(); i++)
std::cout << x[i] << " ";
std::cout << ")\n";
std::cout << x.RunningAverage(0, 1.0) << endl;
return 0;
}
x.RunningAverage(0, 1.0) returns a MVector that cannot be sent to std::cout, unless you declare the operator<< taking a MVector as parameter.
Alternatively, you can replace:
std::cout << x.RunningAverage(0, 1.0) << endl;
By:
MVector av = x.RunningAverage(0, 1.0);
for (int i = 0; i < av.size(); i++)
std::cout << av[i] << " ";
Or, declare the operator:
std::ostream& operator<<(std::ostream& out,const MVector& b)
{
for (int i = 0; i < b.size(); i++)
out << b[i] << " ";
return out;
}
And then std::cout << x.RunningAverage(0, 1.0) << std::endl; will work.
And you can then also replace, in your main function:
for (int i = 0; i < x.size(); i++)
std::cout << x[i] << " ";
By:
std::cout << x;
Live demo: http://cpp.sh/7afyi
You haven't overloaded operator<< for MVector.
You can do that with:
std::ostream& operator<<(std::ostream& output, MVector const& vec)
{
// use "output << …;" to do printing
return output;
}
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
I have a Polynomial and Rational class which manipulates polynomial and rational functions as vectors. I've defined non-member operators for *, /, +, and -, but I don't think I'm getting how to use them correctly (see code below):
#include<iostream>
#include<algorithm>
#include<iterator>
#include<functional>
#include<vector>
#include<cmath>
using namespace std;
class Polynomial
{
public:
Polynomial();
Polynomial(vector<int>coeffs);
friend class Rational;
Accessors
int Degree() const;
int Coefficient(int k) const;
void print() const;
int get_size() const;
vector<int> get_vect() const; // THIS RETURNS coefficient.
void set_vect(vector<int> input); // THIS SETS coefficient TO AN INPUTTED VECTOR OF INTEGERS.
void constantMultiply(int x);
void Transform();
double evaluateAt(double x);
Polynomial& operator++();
Polynomial operator++ (int unused);
Polynomial& operator--();
Polynomial operator-- (int unused);
Polynomial& operator+=(Polynomial name1);
Polynomial& operator-=(Polynomial name2);
Polynomial& operator*=(Polynomial name3);
private:
vector<int> coefficient;
};
poly1 + poly2
Polynomial Add(const Polynomial & poly1, const Polynomial & poly2);
poly1 - poly2
Polynomial Subtract(const Polynomial & poly1, const Polynomial & poly2);
poly1 * poly2
Polynomial Multiply(const Polynomial & poly1, const Polynomial & poly2);
int zero_detect( vector<int> a , int j);
vector<int> flip( vector<int> input );
class Rational
{
public:
Rational();
Rational(Polynomial p);
Rational(Polynomial pN, Polynomial pD);
double evaluateAt(double x);
void print();
Rational& operator++();
Rational operator++(int unused);
Rational& operator--();
Rational operator--(int unused);
Rational& operator+=(Rational name1);
Rational& operator-=(Rational name1);
Rational& operator*=(Rational name1);
Rational& operator/=(Rational name1);
Polynomial get_poly_top(); // SOME SIMPLE ACCESSORS.
Polynomial get_poly_bot();
private:
Polynomial top;
Polynomial bot;
};
Polynomial operator+ (Polynomial a , Polynomial b);
Polynomial operator- (Polynomial a , Polynomial b);
Polynomial operator* (Polynomial a , Polynomial b);
Rational operator+ (Rational a , Rational b);
Rational operator- (Rational a , Rational b);
Rational operator* (Rational a , Rational b);
Rational operator/ (Rational a , Rational b);
bool operator== (Polynomial a , Polynomial b);
bool operator!= (Polynomial a , Polynomial b);
bool operator< (Polynomial a , Polynomial b);
bool operator> (Polynomial a , Polynomial b);
Polynomial sign_swap(Polynomial input); // THIS NEGATES HE COEFFICIENT CELLS, AND HELPS WITH DEFINING SUBTRACTION OFF OF ADDITION.
int main(void)
{
cout << "Welcome! Please input the coefficients of the first polynomial, p." << endl;
cout << "When you are finished, enter -1234." << endl;
vector<int> user_vect1;
vector<int> user_vect2;
int input1;
do
{
cin >> input1;
if(input1 == -1234)
{
continue;
}
else
{
user_vect1.push_back(input1);
}
}while(input1 != -1234); // THIS IS THE USER INPUT GADGET.
cout << endl << endl;
cout << "Your first polynomial is ";
Polynomial user_poly1(user_vect1);
Polynomial temp_poly1(user_vect1);
user_poly1.print();
cout << "." << endl;
cout << "Its transform is ";
user_poly1.Transform();
user_poly1.print();
cout << "." << endl << endl;
cout << "Please input the coefficients of the second polynomial, q." << endl;
int input2;
do
{
cin >> input2;
if(input2 == -1234)
{
continue;
}
else
{
user_vect2.push_back(input2);
}
}while(input2 != -1234);
cout << endl << endl;
cout << "Your second polynomial is ";
Polynomial user_poly2(user_vect2);
Polynomial temp_poly2(user_vect2); // I WANTED A TEMPORARY POLYNOMIAL BECAUSE user_poly(i) GETS TRANSFORMED LATER.
user_poly2.print();
cout << "." << endl;
cout << "Its transform is ";
user_poly2.Transform();
user_poly2.print();
cout << "." << endl << endl;
cout << "p(x)+q(x) = ";
/*FUNCTION CALL*/
(temp_poly1+temp_poly2).print();
cout << endl << endl;
cout << "p(x)-q(x) = ";
/* FUNCTION CALL */
(temp_poly1-temp_poly2).print();
cout << endl << endl;
cout << "p(x)*q(x) = ";
/*FUNCTION CALL */
(temp_poly1*temp_poly2).print();
cout << endl << endl;
cout << "p(x)/q(x) = ";
/*FUNCTION CALL*/
Rational user_rat1(temp_poly1,temp_poly2);
user_rat1.print();
cout << endl << endl;
cout << "p(x)/q(x) + p(x)*q(x) = ";
/*FUNCTION CALL*/
Rational user_rat2(temp_poly1+(temp_poly1)*(temp_poly2*temp_poly2),temp_poly2);
(user_rat2).print();
cout << endl << endl;
cout << "p(x)+1 = ";
/*FUNCTION CALL*/
(++temp_poly1).print();
cout << endl << endl;
cout << "p(x)+2 = ";
/*FUNCTION CALL*/
(++temp_poly1).print();
cout << endl << endl;
--(--temp_poly1);
cout << "(p(x)/q(x))*(1+x^2-3x^4) = ";
/*FUNCTION CALL*/
vector<int> temp_insert;
temp_insert.push_back(1);
temp_insert.push_back(0);
temp_insert.push_back(1);
temp_insert.push_back(0);
temp_insert.push_back(-3); // HERE I'M PUSHING THE VALUES OF THE DESIRED POLYNOMIAL INTO temp_insert.
Polynomial temporary(temp_insert);
Rational temp_rat1(temporary);
(user_rat1*temp_rat1).print(); // <-- RIGHT HERE IS THE BIGGEST ISSUE I'M HAVING. IT'S NOT .print() I DON'T THINK.
cout << endl << endl;
cout << "Does p(x) equal q(x)? ";
/*FUNCTION CALL*/ //<--- Should be a function that is a void, but outputs "Yes." or "No."
if( temp_poly1 == temp_poly2 )
{
cout << "Yes.";
}
else
{
cout << "No.";
}
cout << endl << endl;
cout << "Is p(x) < q(x)? ";
/*FUNCTION CALL*/ //<--- Should be a function that is a void, but outputs "Yes." or "No."
if( temp_poly1 < temp_poly2 )
{
cout << "Yes.";
}
else
{
cout << "No.";
}
cout << endl << endl;
cout << "p(2) = ";
/*FUNCTION CALL*/
temp_poly1.evaluateAt(2);
cout << endl << endl;
cout << "p(3)/q(3)= ";
/*FUNCTION CALL*/
double fun1 = temp_poly1.evaluateAt(3);
double fun2 = temp_poly2.evaluateAt(3);
cout << fun1/fun2;
cout << endl << endl;
};
Polynomial::Polynomial()
{
coefficient.push_back(0);
}
Polynomial::Polynomial(vector<int> coeffs)
{
coefficient = coeffs;
}
int Polynomial::Degree() const
{
int deg = 0;
for (size_t i = 0; i < coefficient.size(); ++i)
{
if (coefficient[i] != 0)
{
deg = i;
}
}
return deg;
}
int Polynomial::Coefficient(int k) const
{
return coefficient[k + 1];
}
void Polynomial::print() const
{
for( size_t i = 0 ; i < coefficient.size() ; ++i )
{
if( coefficient[i] == 0 )
{
continue;
}
else
{
if( i == 0 )
{
cout << coefficient[i];
}
else
{
if(zero_detect(coefficient, i) == i)
{
if( coefficient[i] == 1 || coefficient[i] == -1 )
{
if( coefficient[i] == 1)
{
cout << "";
}
else
{
cout << "-";
}
}
else
{
cout << coefficient[i];
}
if( i == 1 )
{
cout << "x";
}
else
{
cout << "x^" << i;
}
}
else
{
cout << "+";
if( coefficient[i] == 1 || coefficient[i] == -1 )
{
if( coefficient[i] == 1)
{
cout << "";
}
else
{
cout << "-";
}
}
else
{
cout << coefficient[i];
}
if( i == 1 )
{
cout << "x";
}
else
{
cout << "x^" << i;
}
}
}
}
}
}
int Polynomial::get_size() const
{
return coefficient.size();
}
vector<int> Polynomial::get_vect() const
{
return coefficient;
}
void Polynomial::constantMultiply(int x)
{
for( size_t i = 0 ; i < coefficient.size() ; ++i )
{
coefficient[i] *= x;
}
}
void Polynomial::Transform()
{
vector<int> transform;
for( size_t i = 1 ; i < coefficient.size() ; ++i )
{
transform.push_back(coefficient[i]*i);
}
coefficient = transform;
}
double Polynomial::evaluateAt(double x)
{
double product=0;
for(size_t i = 0 ; i < coefficient.size() ; ++i )
{
product += (double)coefficient[i]*pow(x,(double)i);
}
return product;
}
Polynomial Add(const Polynomial& poly1, const Polynomial& poly2)
{
vector<int> Poly1 = poly1.get_vect();
vector<int> Poly2 = poly2.get_vect();
vector<int> Poly3;
if( Poly1.size() < Poly2.size() )
{
for(size_t i = Poly1.size() ; i< Poly2.size() ; ++i )
{
Poly1.push_back(0);
}
}
else if( Poly1.size() > Poly2.size() )
{
for(size_t i = Poly2.size() ; i< Poly1.size() ; ++i )
{
Poly2.push_back(0);
}
}
for( size_t i = 0 ; i < max(Poly1.size(),Poly2.size()) ; ++i )
{
Poly3.push_back(Poly1[i]+Poly2[i]);
}
return Poly3;
}
Polynomial Subtract(const Polynomial & poly1, const Polynomial & poly2)
{
vector<int> Poly1 = poly1.get_vect();
vector<int> Poly2 = poly2.get_vect();
vector<int> Poly3;
if( Poly1.size() < Poly2.size() )
{
for(size_t i = Poly1.size() ; i< Poly2.size() ; ++i )
{
Poly1.push_back(0);
}
}
else if( Poly1.size() > Poly2.size() )
{
for(size_t i = Poly2.size() ; i< Poly1.size() ; ++i )
{
Poly2.push_back(0);
}
}
for( size_t i = 0 ; i < max(Poly1.size(),Poly2.size()) ; ++i )
{
Poly3.push_back(Poly1[i]-Poly2[i]);
}
return Poly3;
}
Polynomial Multiply(const Polynomial & poly1, const Polynomial & poly2)
{
if( poly2.get_size()==1 && poly2.Coefficient(0)==1)
{
return poly1;
}
else
{
vector<int> Poly1 = poly1.get_vect();
vector<int> Poly2 = poly2.get_vect();
vector<int> Poly3;
Poly3.resize(Poly1.size() + Poly2.size() - 1, 0);
for (size_t i = 0; i != Poly1.size(); i++)
for (size_t j = 0; j != Poly2.size(); j++)
Poly3[i+j] += Poly1[i] * Poly2[j];
return Poly3;
}
}
int zero_detect( vector<int> a , int j)
{
int count=0;
for( size_t i = 0 ; i < j ; ++i )
{
if( a[i] == 0 )
{
++count;
}
}
return count;
}
Rational::Rational()
{
vector<int> temp;
temp.push_back(0);
top.set_vect(temp);
++bot;
}
Rational::Rational(Polynomial p)
{
top = p;
++bot;
}
Rational::Rational(Polynomial pN, Polynomial pD)
{
top = pN;
bot = pD;
}
double Rational::evaluateAt(double x)
{
return top.evaluateAt(x)/bot.evaluateAt(x);
}
void Rational::print()
{
top.print();
cout << " / ";
bot.print();
}
Polynomial operator+ (Polynomial a , Polynomial b)
{
return Add(a,b);
}
Polynomial operator- (Polynomial a , Polynomial b)
{
return Subtract(a,b);
}
Polynomial operator* (Polynomial a , Polynomial b)
{
return Multiply(a,b);
}
Rational operator+ (Rational a , Rational b)
{
Rational c((a.get_poly_top()*b.get_poly_bot())+(b.get_poly_top()*a.get_poly_bot()), a.get_poly_bot()*b.get_poly_bot());
return c;
}
Rational operator- (Rational a , Rational b)
{
Rational c((a.get_poly_top()*b.get_poly_bot())+(sign_swap(b.get_poly_top()*a.get_poly_bot())), a.get_poly_bot()*b.get_poly_bot());
return c;
}
Rational operator* (Rational a , Rational b)
{
Rational c(a.get_poly_top()*b.get_poly_top(), a.get_poly_bot()*b.get_poly_bot());
return c;
}
Rational operator/ (Rational a , Rational b)
{
Rational c(a.get_poly_top()*b.get_poly_bot(), a.get_poly_bot()*b.get_poly_top());
return c;
}
Rational& Rational::operator++()
{
Rational c(bot, bot);
return *this+c;
}
Rational Rational::operator++(int unused)
{
Rational copy(*this);
Rational c(bot, bot);
*this = *this+c;
return copy;
}
Rational& Rational::operator--()
{
Rational c(bot, bot);
return *this-c;
}
Rational Rational::operator--(int unused)
{
Rational copy(*this);
Rational c(bot, bot);
*this = *this-c;
return copy;
}
bool operator== (Polynomial a , Polynomial b)
{
vector<int>temp1=a.get_vect();
vector<int>temp2=b.get_vect();
if( a.Degree() != b.Degree() )
{
return false;
}
else
{
for(size_t i = 0 ; i<a.get_size() ; ++i)
{
if( temp1[i]!= temp2[i])
{
return false;
}
}
return true;
}
}
bool operator!= (Polynomial a , Polynomial b)
{
return !(a==b);
}
bool operator< (Polynomial a , Polynomial b)
{
if(a.Degree() < b.Degree())
{
return true;
}
else
{
return false;
}
}
bool operator> (Polynomial a , Polynomial b)
{
if(a.Degree() > b.Degree())
{
return true;
}
else
{
return false;
}
}
Polynomial Rational::get_poly_top()
{
return top;
}
Polynomial Rational::get_poly_bot()
{
return bot;
}
Polynomial sign_swap(Polynomial input)
{
vector<int> temp = input.get_vect();
for(size_t i = 0 ; i<input.get_size() ; ++i )
{
temp[i] *=-1;
}
input.set_vect(temp);
return input;
}
void Polynomial::set_vect(vector<int> input)
{
coefficient = input;
}
Polynomial& Polynomial::operator++()
{
coefficient[0]++;
return *this;
}
Polynomial Polynomial::operator++ (int unused) // &
{
Polynomial copy(*this);
coefficient[0]++;
return copy;
}
Polynomial& Polynomial::operator--()
{
coefficient[0]--;
return *this;
}
Polynomial Polynomial::operator-- (int unused) // &
{
Polynomial copy(*this);
coefficient[0]--;
return copy;
}
Polynomial& Polynomial::operator+=(Polynomial name1)
{
return Add(*this, name1);
}
Polynomial& Polynomial::operator-=(Polynomial name2)
{
return Subtract(*this, name2);
}
Polynomial& Polynomial::operator*=(Polynomial name3)
{
return Multiply(*this, name3);
}
I get an error that says I've got an out-of-range issue with some vector process in the code.
Note:
If you are taking a programming class, and this happens to be your assignment, then please do not copy and paste this code into your source and use it for your own benefit. Instead, use it as a foundation to build off of if you're having trouble.
Any help with resolving this rational multiplication issue, or anything else that seems inefficient, redundant, useless, etc. would be much appreciated. Thank you. :-)
The Problem:
I've created a Rational class that is friend to a Polynomial class, and the one-argument constructor Rational( Polynomial p) sets its top polynomial top to p, which is of data type Polynomial, and sets its bottom polynomial bot to 1, which is of the same data type as top. I've created a Rational object in main using this one-argument constructor passing in a vector I generated manually in main, but when I try to print the product of two rational objects--the first one, user_rat1, being a two-argument type construction with top=p and bot=1 (1 the polynomial)--I get an error saying the bounds of the vector are out of range. I don't see why...
Made sure that you understand the coefficients array/vector's index mean the exponent.
I can suggest for you to use another int data type that hold your degree (for any poly).
(in addition you can add another int data type that hold the currentDegree = the highest degree in the poly that != 0).
For example, if you want to create new Polynomial with highest degree = 4.
Polynomial::Polynomial(int degree){
this->degree = degree;
if(degree == 0)
this->coeffs = new double();
else if (degree > 1)
this->coeffs = new double[degree+1];
else if (degree == 1)
this->coeffs = new double();
for(int i=0;i<=degree;i++)
this->coeffs[i] = 0;
actualDegree = 0;
}
in addition, you can add another constructor when you get array for example:
Polynomial::Polynomial(double* coeffs, int degree){
this->degree = degree;
this->actualDegree = 0;
this->coeffs = new double[degree+1];
for(int i=0;i<=degree;i++){
this->coeffs[i] = coeffs[i];
if (coeffs[i] != 0 && i > actualDegree)
actualDegree = i;
}
}
That will help you in functions when you use any object from Polynomial to know your degree for any object you working with.
If you want you can even made the constructor as template for int\double (but dont forget to set it in class to the pointer)
Source:
Polynomial Multiply(const Polynomial & poly1, const Polynomial & poly2)
{
if( poly2.get_size()==1 && poly2.Coefficient(0)==1)
The problemic method:
int Polynomial::Coefficient(int k) const
{
return coefficient[k + 1];
}
If the size is 1 then you can only reach the coefficient[0] and k + 1 here is 1.
You may meant:
int Polynomial::Coefficient(int k) const
{
return coefficient[k];
}