C++: Mathematical error when adding two polynomials - c++

I'm in the process of writing a Polynomial Class and have overloaded the + operator. I asked a question a few days ago regarding the actual overloading process, and received a great answer. However, my question now is in regards to the actual function of my program.
I need to add two user entered polynomials together. When one adds polynomials one must only add like terms, even if the two polynomials differ in size. My program does ok if the first entered polynomial is larger than the second, but reaches an error if the first polynomial is smaller than the second. To be more specific... I've noticed that it seems to leave one term off. On top of that it seems to add two like terms together and then print it with a different exponent. For example :
2x^3 + 3x^3 = 5x^2.
For reference, this is my previous question regarding this program: Overloading + operator with classes containing array pointers (C++)
Some help would be greatly appreciated.
My Code:
#include<iostream>
#include<stdexcept>
using namespace std;
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
class Polynomial
{
friend istream& operator>>(istream& in, Polynomial& p);
friend ostream& operator<<(ostream& out, const Polynomial& p);
public:
Polynomial(int = 10);
~Polynomial();
void assignExponent();
Polynomial operator+(const Polynomial& other);
private:
int SIZE;
int *exponents;
int *polyPtr;
};
#endif
//CONSTRUCTOR
Polynomial::Polynomial(int arraySize)
{
if(arraySize > 0)
SIZE = arraySize;
else
{
cout << "Array size must be greater than 0. Program will now "
<< "Terminate..." << endl;
system("pause");
exit(0);
}
polyPtr = new int[SIZE];
exponents = new int[SIZE];
for(int i = 0; i<SIZE; i++)
polyPtr[i] = 0;
assignExponent();
};
//DESTRUCTOR
Polynomial::~Polynomial()
{
delete [] polyPtr;
};
//STREAM INSERTION
istream& operator>>(istream& in, Polynomial& p)
{
for(int i = 0; i<p.SIZE; i++)
{
in >> p.polyPtr[i];
}
return in;
};
//STREAM EXTRACTION
ostream& operator<<(ostream& out, const Polynomial& p)
{
int exponent;
for(int i = 0; i<p.SIZE; i++)
{
exponent = (p.SIZE - 1) - i;
if(p.polyPtr[i] != 1)
{
if(exponent > 0 && exponent != 1)
out << p.polyPtr[i] << "x^" << exponent << " + ";
if(exponent == 1)
out << p.polyPtr[i] << "x" << " + ";
if(exponent == 0)
out << p.polyPtr[i];
}
//In order to not display coefficient if = 1
else
{
if(exponent > 0 && exponent != 1)
out << "x^" << exponent << " + ";
if(exponent == 1)
out << "x" << " + ";
if(exponent == 0)
out << p.polyPtr[i];
}
}
return out;
};
//Assigns a value for exponent
void Polynomial::assignExponent()
{
for(int i = 0; i<SIZE; i++)
{
exponents[i] = (SIZE - 1) - i;
}
};
//OVERLOAD OF + OPERATOR
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum(SIZE);
int difference;
//If the first polynomial is larger
if (SIZE > other.SIZE)
{
difference = SIZE - other.SIZE;
for(int i = 0; i<SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = polyPtr[i];
else
{
sum.polyPtr[i] = polyPtr[i] +
other.polyPtr[i - difference];
}
}
}
//If the second polynomial is larger **PROBLEM***************************************
if(other.SIZE > SIZE)
{
difference = other.SIZE - SIZE;
for(int i = 0; i<other.SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = other.polyPtr[i];
else
{
sum.polyPtr[i] = other.polyPtr[i] +
polyPtr[i - difference];
}
}
}
//If the polynomials are equal
if(SIZE == other.SIZE)
{
for(int i = SIZE-1; i >= 0; i--)
{
sum.polyPtr[i] = polyPtr[i] + other.polyPtr[i];
}
}
return sum;
};
int main()
{
int polySize;
//User enters a size for the first & second polynomial
cout << "Enter a size for the first polynomial: ";
cin >> polySize;
Polynomial pOne(polySize);
cout << "\nEnter a size for the second polynomial: ";
cin >> polySize;
Polynomial pTwo(polySize);
//User enters in values (Overload of >> operator
cout << "\n\nEnter in values for the first polynomial, "
<< "in the format - (x x x x): " << endl;
cin >> pOne;
cout << "\nEnter in values for the second polynomial, "
<< "in the format - (x x x x): " << endl;
cin >> pTwo;
//Overload << operator for output
cout << "\nPolynomial 1 is: " << pOne << endl
<< "Polynomial 2 is: " << pTwo << endl;
Polynomial pThree = pOne + pTwo;
cout << "\nAfter being added together, the new polynomial is: "
<< pThree << endl;
system("pause");
}
Output Window:

The SIZE of sum should be the maximum of the SIZE of the two polynomials:
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum( max(SIZE,other.SIZE) );
Otherwise your new Polynomial is only as large as the polynomial you're doing the operation on, and you will be writing to unallocated memory further down the loop:
for(int i = 0; i<other.SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = other.polyPtr[i];
else
{
sum.polyPtr[i] = other.polyPtr[i] +
polyPtr[i - difference]; // i may be higher than SIZE, thus sum.polyPtr[i] invokes undefined behaviour.
}
}

The current first problem is here:
Polynomial sum(SIZE);
Better:
Polynomial sum(std::max(SIZE, other.SIZE));
But I think the real problem is that you need to simplify your design.
The first thing could be to use:
private:
int SIZE;
double *coef;
};
Simple keep the coeficient for ax^n in coef[n]=a. Now is tryvial to find out what elemnt you need to add.
But much simpler could be to use
std::map<int,double> p; to store all. p[n]=a;
Without debugging and optimizing, just an idea:
private:
std::map<int,double> p;
};
And forget about any new, delete and index out of range.
The +() will be like:
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum; // No SIZE more.
sum.p= p;
for (auto ax_n : other.p)
sum.p[ax_n.first] += ax_n.second;
return sum;
}

Your problem lies in the construction of sum(SIZE)
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum(SIZE);
If you do this, and the first polynomial is only of size 2, later in the method you are copying into memory that isn't yours:
if(other.SIZE > SIZE)
{
difference = other.SIZE - SIZE;
////HERE IS YOUR PROBLEM - your loop uses other.SIZE, which is larger than SIZE...
for(int i = 0; i<other.SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = other.polyPtr[i];
else
{
sum.polyPtr[i] = other.polyPtr[i] +
polyPtr[i - difference];
}
}
}
The error happens because you use sum.polyPtr[i], which when the SIZE < other.SIZE occurs, doesn't exist.

Your code is way too over-complicated. Something like this does it nicely:
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <sstream>
// helper to read the input polynomials into a output-iterator
template<class OutIter>
void read_vector(std::istream& is, OutIter first)
{
// helper type to iterate over the input coefficients
typedef std::istream_iterator<
typename OutIter::container_type::value_type> iter_t;
// buffer to hold the input line
std::string buffer;
// read it
std::getline(is, buffer);
// create a string stream with which we tokenize the input
std::istringstream iss(buffer);
// read coefficients into output container
std::copy(iter_t(iss), iter_t(), first);
}
int main()
{
std::vector<double> p1, p2;
// read input
std::cout << "Enter coefficients of the first polynomial: ";
read_vector(std::cin, std::back_inserter(p1));
std::cout << "Enter coefficients of the second polynomial: ";
read_vector(std::cin, std::back_inserter(p2));
// check for errors
if (p1.empty() || p2.empty())
{
std::cerr << "Error: polynomials must not be empty\n";
return 1;
}
// initialize result polynomial to 0. coefficients
std::vector<double> p3(std::max(p1.size(), p2.size()), 0.);
// copy first polynomial to the result, starting from the back
std::copy(p1.rbegin(), p1.rend(), p3.rbegin());
// add second polynomial, starting from the back
std::transform(p2.rbegin(), p2.rend(), p3.rbegin(), p3.rbegin(),
std::plus<double>());
// print result
std::cout << "Sum: ";
const size_t n = p3.size()-1;
for (size_t i=0; i < n; ++i)
{
std::cout << std::showpos << p3[i] << "x^" << n-i;
}
std::cout << std::showpos << p3[n] << "\n";
}

Related

How to pass an array to a class?

#include <iostream>
#include <string>
using namespace std;
class Term;
class Polynomial;
class Term {
public:
friend class Polynomial;
void set_term(string s);
int get_pow();
int get_coefficient();
private:
int coefficient;
int pow;
};
class Polynomial {
public:
friend class Term;
Polynomial(int s, Term t[]);
int get_size();
Term *myterm;
private:
int P_size;
};
void Term::set_term(string s) {
coefficient = stoi(s.substr(1, 1));
pow = stoi(s.substr(4, 1));
if (s[0] == '-') {
coefficient = -coefficient;
}
}
int Term::get_coefficient() { return coefficient; }
int Term::get_pow() { return pow; }
Polynomial::Polynomial(int s, Term t[]) {
P_size = s;
myterm = new Term[s];
for (int i = 0; i < s; i++) {
myterm[i].coefficient = t[i].coefficient;
cout << i << " Term " << t[i].coefficient << endl;
cout << i << " Polynomial " << myterm[i].coefficient << endl;
myterm[i].pow = t[i].pow;
}
}
Polynomial::get_size() { return P_size; }
int main() {
string x1;
cin >> x1;
int size_x1 = x1.size();
Term term1[size_x1];
for (int i = 0; i < size_x1; i += 5) {
term1[i].set_term(x1.substr(i, 5));
}
Polynomial p1(size_x1 / 5, term1);
for (int i = 0; i < size_x1; i += 5) {
cout << term1[i].get_coefficient() << "x^";
cout << term1[i].get_pow() << endl;
}
cout << "------------------" << endl;
for (int i = 0; i < p1.get_size(); i++) {
if (p1.myterm[i].get_coefficient() > 0)
cout << "+";
cout << p1.myterm[i].get_coefficient();
cout << "x^";
cout << p1.myterm[i].get_pow() << endl;
}
return 0;
}
term1 in main is working right but when I pass it to p1(Polynomial) just t[0] and, myterm[0]
is true I mean I pass term1 to p1 as t so t[0] = term1[0] and myterm[0] = t[0]
Polynomial::Polynomial(int s, Term t[]) {
P_size = s;
myterm = new Term[s];
for (int i = 0; i < s; i++) {
myterm[i].coefficient = t[i].coefficient;
cout << i << " Term " << t[i].coefficient << endl;
cout << i << " Polynomial " << myterm[i].coefficient << endl;
myterm[i].pow = t[i].pow;
}
}
in Polynomial constructor both t[1].coeffient and, myterm[1].coefficient are 4941660(for instance)
however, t is term1 and in term1 term1[1] is the 4(for instance)
if term1[1] is 4 so t[1] should be 4 but it's not so myterm[1], is not 4 too.
There's a lot of confusion over sizes here
string x1;
cin >> x1;
int size_x1 = x1.size();
Term term1[size_x1];
for (int i = 0; i < size_x1; i += 5) {
term1[i].set_term(x1.substr(i, 5));
}
Polynomial p1(size_x1 / 5, term1);
You didn't say what your input is, but suppose it is "1234567890" then size_x1 equals 10, so term1 will also have size 10. Then your for loop will execute twice, with i equal to 0 and i equal to 5, so you will assign 12345 to term1[0] and 67890 to term1[5]. That makes no sense to me. term1 has size 10 but the only elements assigned to are zero and five.
Then you create p1 with size size_x1/5 which equals 2. So the constructor for p1 will look at term1[0] and term1[1], but in the for loop you assigned to term1[0] and term1[5].
You have to think carefully about what the code you are writing is actually doing. The compiler will do exactly what you tell it to. It's not like talking to a person who can understand what you really meant. So you have to be very careful. This is I think you really meant (but I could be wrong)
string x1;
cin >> x1;
int size_x1 = x1.size();
int size_term1 = size_x1/5;
Term term1[size_term1];
for (int i = 0; i < size_term1 ; ++i) {
term1[i].set_term(x1.substr(5*i, 5));
}
Polynomial p1(size_term1, term1);
I created a new variable size_term1 with the size of the term array, which is now the sizeof the input divided by 5. And I changed the for loop so that it assigns to term1[0] and term1[1].
So your problem has nothing to do with passing an array to a class, which you did perfectly correctly. It was not thinking clearly about the code you were writing, and making mistakes in the logic.

BigInt calculator spitting out slightly wrong results

So for my assignment I have to create a calculator that works with big integers up to 256 characters in length. The current part of the assignment I'm up to is getting it work with multiplication of larger numbers. DIGITS is the limit of digits per Bigint class, currently set to 20 for debug sake, but will go up to 256
When doing a calculation like 25 * 137, I get the answer 3285 when it should be 3425. When I look through the couts that I put in place for debug, the first iteration of the i loop works perfectly and adds 685 to sum which is 5 * 137, so that works perfect. However when it gets to the bit where it's having to do the second iteration of the i loop where it is 20 * 137, it's getting the answer wrong and I cannot work out why. I have an inkling that it's something to do with the carry being two digits (14), but I still can't really work out how I can fix it.
The main implementation that obviously has something wrong with it is in the * operator of the bigint class. I know it's not to do with the << or >> operators as they work perfectly for addition and subtraction.
Full code of the bigint class is below:
#include <iostream>
#include <string>
#include "Bigint.h"
#include <cmath>
using namespace std;
Bigint::Bigint()
{
for (int i = DIGITS-1; i >= 0; --i) {
digits_[i] = 0;
}
}
ostream& operator<< (ostream& out, const Bigint& n)
{
string s = "";
bool found = false;
for (int i = DIGITS - 1; i >= 0; --i) {
if(n.digits_[i] > 0) {
found = true;
}
if(n.digits_[i] != 0 || found == true) {
s += char(n.digits_[i] + '0');
}
}
if (s == "") {
s = "0";
}
return out << s;
}
istream& operator>> (istream& in, Bigint& n)
{
// Extracts full-length number (does not work for any other length).
// All characters are assumed to be valid digits.
//
string s;
if (in >> s) {
for (int i = 0; i < DIGITS; ++i) {
n.digits_[i] = i < s.length() ? s[s.length() - 1 - i] - '0' : 0;
}
}
return in;
}
Bigint operator+ (const Bigint& n1, const Bigint& n2)
{
Bigint ret;
int cur_carry = 0;
for(int i = 0; i < DIGITS; ++i) {
int n1_digit = n1.get(i);
int n2_digit = n2.get(i);
if(n1_digit < 0 || n1_digit > 9) {
n1_digit = 0;
}
if(n2_digit < 0 || n2_digit > 9) {
n2_digit = 0;
}
//printf("n1 : %d\n", n1_digit);
//printf("n2 : %d\n", n2_digit);
int sum = n1_digit + n2_digit + cur_carry;
//cout << "sum : " << sum << endl;
cur_carry = Bigint::getCarry(sum);
//cout << "new carry : " << cur_carry << endl;
ret.set(i, Bigint::getDigitValue(sum));
//cout << "Set : " << i << "," << Bigint::getDigitValue(sum) << endl;
}
return ret;
}
Bigint operator* (const Bigint& n1, const Bigint& n2)
{
Bigint ret;
//int borrowed = 0;
Bigint sum;
for(int i = 0; i < DIGITS ; i++){
int n1_digit = n1.get(i);
//cout << "n2: " << n2_digit << endl;
Bigint temp;
if(n1_digit < 0 || n1_digit > 9) {
n1_digit = 0;
}
int carry = 0;
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * (pow(10, i)) * n2.get(j);
cout << "n1: " << n1_digit << endl;
cout << "n2: " << n2.get(j) << endl;
if(carry != 0){
temp.set(j, (Bigint::getDigitValue(val)) + carry);
cout << "Carry was " << carry << ", now set 0" << endl;
cout << "value to set: " << (Bigint::getDigitValue(val)) + carry << endl;
carry = 0;
}
else if(carry == 0){
temp.set(j, Bigint::getDigitValue(val));
cout << "value to set: " << (Bigint::getDigitValue(val))<< endl;
}
carry = (Bigint::getCarry(val) + carry);
cout << "carry: " << carry << endl;
}
cout << "Sum before adding temp: " << sum << endl;
sum = sum + temp;
cout << "Sum after adding temp: " << sum << endl;
}
ret = sum;
return ret; // Only correct when n2 equals 1.
}
int Bigint::get(int pos) const {
//Return address of digit for reading
int ret = digits_[pos];
return ret;
}
void Bigint::set(int pos, int val) {
this->digits_[pos] = val;
}
int Bigint::getCarry(int val) {
//Integer division, always floors
return val/10;
}
int Bigint::getDigitValue(int val) {
return val % 10;
}
Header file:
#ifndef BIGINT_H_
#define BIGINT_H_
#define DIGITS 20
class Bigint
{
public:
/**
* Creates a Bigint initialised to 0.
*/
Bigint();
/**
* Inserts n into stream or extracts n from stream.
*/
friend std::ostream& operator<< (std::ostream &out, const Bigint& n);
friend std::istream& operator>> (std::istream &in, Bigint& n);
/**
* Returns the sum, difference, product, or quotient of n1 and n2.
*/
friend Bigint operator* (const Bigint& n1, const Bigint& n2);
friend Bigint operator+ (const Bigint& n1, const Bigint& n2);
int get(int pos) const;
void set(int pos, int val);
static int getCarry(int val);
static int getDigitValue(int val);
private:
int digits_[DIGITS];
};
#endif // BIGINT_H_
Main:
#include <iostream>
#include "Bigint.h"
using namespace std;
int main(int argc, char *argv[])
{
Bigint n1, n2;
char op;
while (cin >> n1 >> op >> n2) {
switch (op) {
case '+' :
cout << n1 + n2 << endl;
break;
case '*' :
cout << n1 * n2 << endl;
break;
}
}
return 0;
}
}
you should not use this lineint val = n1_digit * (pow(10, i)) * n2.get(j);
because it will give integer overflow since you are working with bigintger
instead use the digits in the multiplier and add zeros behind the result.
the number of zeros to add will depend on the position of the multiplier digit which you can find the variable i from this loop for(int i = 0; i < DIGITS ; i++) in the overloaded * function
There are a few potential problems
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * (pow(10, i)) * n2.get(j); // val % 10 == 0 for i > 0
// You should also be adding the carry to val
cout << "n1: " << n1_digit << endl;
cout << "n2: " << n2.get(j) << endl;
if(carry != 0){
temp.set(j, (Bigint::getDigitValue(val)) + carry);
// This can set temp[j] to values above 9 depending on the carry
cout << "Carry was " << carry << ", now set 0" << endl;
cout << "value to set: " << (Bigint::getDigitValue(val)) + carry << endl;
carry = 0;
}
else if(carry == 0){
temp.set(j, Bigint::getDigitValue(val));
cout << "value to set: " << (Bigint::getDigitValue(val))<< endl;
}
carry = (Bigint::getCarry(val) + carry);
cout << "carry: " << carry << endl;
}
Because you multiply by a power of 10, getDigitValue and getCarry aren't acting the way you expect them to. It might be better to shift the index for temp.set up by i instead of multiplying by pow(10, i).
I would also recommend cleaning up the cases. Both the if and the else if are actually doing the same work in this case, and resetting the carry doesn't do anything. So this would have the exact same behavior:
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * (pow(10, i)) * n2.get(j);
temp.set(j, (Bigint::getDigitValue(val)) + carry);
// If the carry is 0, the addition doesn't do anything
// You don't need to reset the carry to 0, since it's assigned here anyway
carry = (Bigint::getCarry(val) + carry);
}
Without the cases and without the print statements, it's much easier to read, but here the use of methods (getCarry and getDigitValue) still makes it hard to see the problem by moving the relevant operations to the bottom of the class. Making the changes gives:
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * n2.get(j) + carry;
temp.set(i + j, Bigint::getDigitValue(val));
carry = Bigint::getCarry(val);
// The carry just gets added to the value at the beginning
// Everything else just works that way
}
You also need to change the get and set functions so that they don't work out of bounds:
int Bigint::get(int pos) const {
//Return address of digit for reading
if (pos >= DIGITS)
return 0;
int ret = digits_[pos];
return ret;
}
void Bigint::set(int pos, int val) {
if (pos >= DIGITS)
return ;
this->digits_[pos] = val;
}
With this code, I get 3425 for 25 * 137.

Odd results after first float entered

I have created a program to take in float values until a non-number is entered. The program will then print the numbers entered like {n0,n1,...,}, as well as sum up the number entered and compute the average.
My problem is after n0 is printed out all the rest of the numbers being printed out are not matching the number entered.
Here is the program:
#include <iostream>
using namespace std;
class ManagedArray
{
float *elements;
int numberOfElements;
public:
ManagedArray(float *ele, int NOE)
: elements(ele), numberOfElements(NOE)
{}
ManagedArray()
{
elements = NULL, numberOfElements = 0; //default constructor
}
int Size();
float get(int index);
void add(float value);
~ManagedArray(); // Destructor
ManagedArray(ManagedArray & ma); // copy constructor
void print(ManagedArray ma);
};
float ManagedArray::get(int index) { return elements[index]; }
int ManagedArray::Size() { return numberOfElements; };
void ManagedArray::add(float value)
{
float * biggerArray = new float[numberOfElements + 1];
if (elements != NULL)
{
// copy the old elements into the biggerArray
for (int i = 0; i < numberOfElements; i++)
{
biggerArray[i] = elements[i];
}
// the old array is not needed anymore, we have a better copy
delete[] elements;
}
// point at the new array
elements = biggerArray;
numberOfElements = numberOfElements + 1;
// put the new number into the last element of the array
elements[numberOfElements - 1] = value;
}
ManagedArray::~ManagedArray() { delete[] elements; }
ManagedArray::ManagedArray(ManagedArray & ma)
{
elements = new float[10]; // put here to get the number of input here
for (int i = 0; i <10; i++) // put here to get the number of input here
{
elements[i] = ma.elements[i];
}
numberOfElements = ma.numberOfElements;
}
void ManagedArray::print(ManagedArray ma)
{
bool hasNumbers = ma.Size() > 0;
if (hasNumbers) {
// print the stored numbers
cout << "Entered numbers: " << endl;
cout << "{";
for (int i = 0; i < ma.Size(); ++i)
{
if (i > 0)
{
cout << ", ";
}
cout << ma.get(i);
}
cout << "}" << endl;
float sum = 0;
for (int i = 0; i < ma.Size(); ++i)
{
sum += ma.get(i);
}
cout << "total: " << sum << endl;
cout << "average: " << (sum / ma.Size()) << endl;
}
else {
cout << "no numbers entered." << endl;
}
}
int main()
{
ManagedArray mArray; // default constructor call for ManagedArray
float userInput;
bool addingNumbersToTheList;
cout << "Keep entering numbers. Enter a non-number to stop." << endl;
do
{
cin >> userInput;
addingNumbersToTheList = !std::cin.fail();
if (addingNumbersToTheList) {
mArray.add(userInput);
}
} while (addingNumbersToTheList);
ManagedArray copy(mArray);
// fix cin after intentionally breaking it above.
if (std::cin.fail())
{
std::cin.clear();
while (std::cin.get() != '\n');
}
copy.print(copy);
copy.print(copy);
cin.get();
return 0;
}
So for instance I enter 1 , 2 , 3 , a
the program would print out {1, -4.22017e+37, 2.89451e+31}
Could someone point out what I am doing wrong with this method?
EDIT: I have fixed the copy constructor. Can someone show me how I would replace
the number 10 with the total of numbers input? in:
elements = new float[10];
and
for (int i = 0; i <10; i++)
I needed to iterate through every possible number in the array with a for loop and an array.
elements = new float[ma.Size()];
for (int i = 0; i < ma.Size(); i++)
{
elements[i] = ma.elements[i];
}
numberOfElements = ma.numberOfElements;

C++ Dynamic Arrays and Pointers in Polynomial program causes exit error 255

I'm currently doing a program that read in a degree, and coefficients and creates a polynomial struct. The program can add and multiply the polynomials, then output the sum or product. The program runs, outputs the correct answer, and then gets a windows error:
poly.exe has stopped working
A problem cause the program to stop working correctly. Windows will close the program and notify you if a solution is available.
then scite shows an exit code: 255
I think it could be something in the double for loop I am using for the multiply poly, or with the initialization of the pointer to the array of coefficients. But I cannot figure out what. The could I am using for it is as follows:
#include <iostream>
#include <stdio.h>
using namespace std;
struct Poly {
int degree;
int *coeff; //array of coefficients from lowest degree to highest degree
};
//Reads the coefficients of a polynomial from standard input
//Creates a poly struct and returns a pointer to the poly
Poly* readPoly();
//Outputs a polynomial to standard output with the variable x
void outputPoly(const Poly* p, char x);
//Computes the sum of two polynomials and returns
//a pointer to the new poly struct which is their sum
Poly* addPoly(const Poly* a, const Poly* b);
//Computes the product of two polynomials and returns
//a pointer to the new poly struct which is their product
Poly* multPoly(const Poly* a, const Poly* b);
//Returns to the heap the memory allocated for the polynomial
//and sets p to the nullptr
void deletePoly(Poly* &p);
Poly* readPoly() {
int deg;
//Read the highest degree
cout << "Input the degree: ";
cin >> deg;
//Handles when the degree is == 0
if(deg == 0) {
int *C = new int[deg+1];
Poly *p;
p = new Poly;
p->degree = deg;
p->coeff = C;
return p;
}
int *C = new int[deg+1];
//Read the coefficients
cout << "Input the coefficients: ";
for(int i = 0; i <= deg; i++) {
cin >> C[i];
}
//Create a new poly structure, assign its fields
//and retun a pointer to the new structure
Poly *p;
p = new Poly;
p->degree = deg;
p->coeff = C;
return p;
}
void outputPoly(const Poly* p, char x) {
//Set the degree and cooefficients to be used in the loop
int d = p->degree;
int *C = p->coeff;
//Output the polynomial, depending on the degree/coeff
for(int i = 0; i <= d; i++) {
//if the coeff is zero, and the degree is > 1
if(C[i] == 0 && i > 0)
continue; //Skip the +
//if the degree is 0, and the coeff is 0
else if(i == 0 && C[i] == 0) {
cout << C[i];
continue; //Skip the +
}
//if the degree is 0, and the coeff is not 0
else if(i == 0 && C[i] != 0)
cout << C[i];
//if the degree is 1, and the coeff is 0
else if(C[i] == 0 && i == 1)
cout << x;
//if the degree is 1, and the coeff is 1
else if(C[i] == 1 && i == 1)
cout << x;
//if the degree is 0, and the coeff is > 0
else if(C[i] > 0 && i == 0)
cout << C[i] << "*" << x;
//if the coefficient is 1
else if(C[i] == 1)
cout << x << "^" << i;
//if the degree is 1
else if(i == 1)
cout << C[i] << "*" << x;
//any other circumstance
else
cout << C[i] << "*" << x << "^" << i;
//Print a +, as long as it's not the last term
if(i != d)
cout << " + ";
}
}
void deletePoly(Poly* &p) {
delete[] p->coeff; //Delete the array first
delete p;
p = nullptr;
}
const Poly* getLargest(const Poly* a, const Poly* b) {
//Helper function to get the larger polynomial, given two
if(a->degree > b->degree)
return a;
else
return b;
}
const Poly* getSmallest(const Poly* a, const Poly* b) {
//Helper function to get the smaller polynomial, given two
if(a->degree < b->degree)
return a;
else
return b;
}
Poly* addPoly(const Poly* a, const Poly* b){
int i, j;
int *polyOneC = a->coeff;
int *polyTwoC = b->coeff;
//The new polynomials degree is the size of the polynomial that is the largest
int polyThreeD = getLargest(a, b)->degree;
int *polyThreeC = new int[polyThreeD];
for(i = 0, j = 0; j <= polyThreeD; i++, j++) {
//If the polynomials are of different size,
//then any coefficent term over the size
//of the smaller polynomial degree stays the same
if(i > getSmallest(a, b)->degree)
polyThreeC[i] = getLargest(a, b)->coeff[i];
else
//Otherwise, just add them
polyThreeC[i] = polyOneC[j] + polyTwoC[j];
//"Shifts" if it's equal to zero
if(polyThreeC[i] == 0)
i--;
}
//Ensures the remaining terms have a coefficient value(0)
while(i <= polyThreeD) {
polyThreeC[i] = 0;
i++;
}
Poly *sumPoly;
sumPoly = new Poly;
sumPoly->degree = polyThreeD;
sumPoly->coeff = polyThreeC;
return sumPoly;
}
Poly* multPoly(const Poly* a, const Poly* b) {
//Get the degrees and arrays of coefficients
int polyOneD = a->degree;
int polyTwoD = b->degree;
int *polyOneC = a-> coeff;
int *polyTwoC = b-> coeff;
int polyThreeD = polyOneD + polyTwoD;
int *polyThreeC = new int[polyThreeD + 1];
//Initialize the array of coefficients
for(int i = 0; i <= polyThreeD; i++)
polyThreeC[i] = 0;
//Multiple the coeffients and add to the position of the degree
for(int i = 0; i <= polyOneD; i++) {
for(int j = 0; j <= polyTwoD; j++) {
polyThreeC[i + j] += (polyOneC[i] * polyTwoC[j]);
}
}
//Create a new polynomial pointer and return it
Poly *productPoly;
productPoly = new Poly;
productPoly->degree = polyThreeD;
productPoly->coeff = polyThreeC;
return productPoly;
}
int main() {
Poly *x = readPoly();
Poly *y = readPoly();
//Test the add poly function
cout << "(";
outputPoly(x, 'x');
cout << ")";
cout << " + ";
cout << "(";
outputPoly(y, 'x');
cout << ")";
cout << endl;
//Call addPoly
Poly *z = addPoly(x, y);
cout << "= ";
cout << "(";
outputPoly(z, 'x');
cout << ")";
cout << endl;
cout << endl;
//Test the multiply poly function
cout << "(";
outputPoly(x, 'x');
cout << ")";
cout << " * ";
cout << "(";
outputPoly(y, 'x');
cout << ")";
cout << endl;
//Call multPoly
z = multPoly(x, y);
cout << "= ";
cout << "(";
outputPoly(z, 'x');
cout << ")";
cout << endl;
//Delete the polynomials now that we are done with them
deletePoly(x);
deletePoly(y);
deletePoly(z);
}
one other thing is that the error doesn't occur everytime it's run, so far I've witnessed it when I enter a polynomial with a degree of say 4. As opposed to a polynomial with a degree of 2, it works fine.
Can anyone help me!
You allocated coefficient array in addPoly (polyThreeC) isn't big enough. You forgot to add one to the degree when allocating the array.

Find odd vector elements C++

So I have written a small program that calculates A[0]*B[0] - A[1]*B[1] - A[2]*B[2] - ... - A[n-1]*B[n-1] using vectors.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
double CalcProduct(vector<double> v1,vector<double> v2){
size_t size; int i = 0;
vector<double> product;
double input, input2;
cout << "Enter vector size: ";
cin >> size;
cout << "Enter values for first vector: ";
while (i++ != size) {
cin >> input;
v1.push_back(input);
}
i = 0;
cout << "Enter values for second vector: ";
while (i++ != size) {
cin >> input2;
v2.push_back(input2);
}
double result = 0.0;
if (size >= 1) {
result += v1[0] * v2[0];
for (int i = 1; i < size; ++i)
result -= v1[i] * v2[i];
}
cout << "\nThe 'happy' product of both vectors is: " << result << endl;
}
int main()
{
vector<double> v1;
vector<double> v2;
CalcProduct(v1,v2);
return 0;
}
However, what would happen if I want to compute A[1]*B[1] - A[3]*B[3] - A[5]*B[5] - ....? I tried adding +1 to v1 and v2 before they sum up in result but my logic seems to be wrong. Sample input:
5
1 2 3 4 5
4 5 6 7 5
Expected output: -18
You're doing the calculation in this loop
for(int i = 1; i < size; ++i)
result -= v1[i] * v2[i];
so instead of incrementing i, you can make jumps of 2:
for(int i = 1; i < size; i+=2) {
result -= v1[i] * v2[i];
}
Note that it's a good practice to check that you're not running out of bounds, also I like to surround body of for loop with { and } even if it contains one line.
Edit: I didn't note that you already added the first element before the loop, you can easily solve this by starting from i=3 instead of 1.
First of all, calcProduct is doing three things at once: Reading the values, calculating the product and writing the result to the output. Hence, you should split that into two methods and maybe do the printout from main().
Secondly, once you have generated the vectors, you can use vector.size() to avoid out of bounds situations by checking loop counters against it.
// give vector as reference
void ReadInput(vector<double>& v1,vector<double>& v2)
{
size_t size = 0; // use size_t here as this will be well defined
size_t i = 0; // on 32 and 64 bit architectures
// maybe you should have more error handling here as
// one might desire size to be in some application
// specific range
cout << "Enter vector size: ";
cin >> size;
cout << "Enter values for first vector: ";
while (i++ != size)
{
cin >> input;
v1.push_back(input);
}
i = 0;
cout << "Enter values for second vector: ";
while (i++ != size)
{
cin >> input2;
v2.push_back(input2);
}
}
// giving the parameters as (const) references avoids unneccessary copying
// of data
double CalcProduct(const vector<double>& v1, const vector<double>& v2,
size_t start, size_t step)
{
double result = 0.0;
// do parameter checking before the calculation in order to keep
// the code more structured (e.g. this can be move to a seperate
// function if it gets too complex
if ( v1.size() != v2.size()
|| start > v1.size()
|| start+step > v1.size())
|| start < 1 )
{
throw out_of_range("CalcProduc(): parameter mismatch");
}
result = v1[start] * v2[start];
for (size_t i = start+step; i < v1.size(); i+=step)
{
result -= v1[i] * v2[i];
}
return result;
}
int main()
{
vector<double> v1;
vector<double> v2;
ReadInput(v1, v2);
cout << "\nThe 'happy' product of both vectors is: " << CalcProduct(v1, v2, 1, 2) << endl;
return 0;
}