A while back i wanted to develop an application that calculated the integral of any polynomial that was input but I felt it was lacking the capability to to find more complex polynomials such as:

(x^2+x)/(x^2+x^3)

Unfortunately my attempts at implementing a numerator and denominator as part of the program have failed. So far I have written the following code:

#include <iostream>
#include <sstream>
#include <string>
#include <math.h>
#include <iomanip>

using namespace std;

double f1(double a, double b, double e) //My function for the y values
{
    double y, h;
    h=(powf(a, b)); //x term
    y=(e)*(h); //numerator for the function
    return (y);
}

void ParseTerm(string term, double& coeff, double& exp)
{
    const string TOKEN = "x^"; //The term to replace
    const int TOKEN_LENGTH = TOKEN.length(); //The length of the search term
    const int index = term.find(TOKEN); //Finds the term in the string and writes the position as an integer
    term.replace(index, TOKEN_LENGTH, " "); //Replaces the term at position index with a space
    stringstream ss (term, stringstream::in | stringstream::out); //The non-spaced characters in the string are designated ss
    ss >> coeff; //Outputs the preceding number in the stream as the coefficient
    ss >> exp; //Outputs the following number in the stream as the exponent
}

void TurnPlusesToSpaces (string& equation)
{
    int foundp, foundm;
    foundp=equation.find("+");
    foundm=equation.find("-");
    while (foundp*foundm != 1) {
            const string TOKENA = "+"; //The term to replace
            const int TOKENA_LENGTH = TOKENA.length(); //The length of the search term
            int indexa = equation.find(TOKENA); //Outputs the position of the term as an integer
            if (indexa!=-1) {
            equation.replace(indexa, TOKENA_LENGTH, " "); //Replaces the term with a space in the string equation
            }
            //cout << equation << "\n";//Debug purposes, outputs equation in current loop
            const string TOKENB = "-"; //The term to replace
            const int TOKENB_LENGTH = TOKENB.length(); //The length of the search term
            int indexb = equation.find(TOKENB); //Outputs the position of the term as an integer
            if (indexb!=-1) {
            equation.replace(indexb, TOKENB_LENGTH, " ");
            }
            foundp=equation.find("+");
            //cout << foundp;
            foundm=equation.find("-");
            //cout << foundm;
            //cout << equation << "\n";
    }
}

int main()
{
    double coeffn, expn, coeffd, expd, Suma, Sumb, xmin, xmax, x, inc, y1, y2, y, Area; //Declaration of essential variables
    int k;
    k = 1;
    string terma, termb;
    string numerator = "1x^2+2x^1+1x^0"; //Declaration of the string for the numerator
    string denominator = "1x^2+2x^1+1x^0";
    do {
        Suma = 0;
        Sumb = 0;
        cout << "\n" << "What is the numerator? \n";
        cin >> numerator; //Input for the numerator
        cout << "\n" << "What is the denominator? \n";
        cin >> denominator; //Input for the denominator
        /*cout << "How many plus signs exist in the numerator? \n";
        cin >> re; //Input for number of plus signs*/
        cout << "What is the lower boundary? \n";
        cin >> xmin; //The lower boundary
        cout << "What is the upper boundary? \n";
        cin >> xmax; //The upper boundary
        cout << "In what increments do you wish to integrate? \n";
        cin >> inc; //Steps between each calculation, increases calculation time
        string term = "000x^000"; //Test term
        x = xmin; //Sets x to the first value
        xmax -= inc; //Prevents inaccuracy due to the upper boundary
        TurnPlusesToSpaces (numerator); //Calls earlier function
        //cout << numerator << "\n"; //Outputs the numerator
        stringstream ssa(numerator, stringstream::in | stringstream::out);
        //cout << terma << "\n";
        TurnPlusesToSpaces (denominator); //Calls earlier function
        //cout << denominator << "\n"; //Outputs the numerator
        stringstream ssb(denominator, stringstream::in | stringstream::out);
        //cout << termb << "\n";
        do {
        while (ssa >> terma) {
        ParseTerm(terma, coeffn, expn);
        cout << coeffn << " " << expn << "\n";
        y1=fabs(f1(x, expn, coeffn)); //First y value
        //cout << y1;
        Sumb+=y2;
        };
        while (ssb >> termb) {
        ParseTerm(termb, coeffd, expd);
        cout << coeffd << " " << expd << "\n";
        y2=fabs(f1(x, expd, coeffd)); //First y value
        //cout << y2;
        Sumb+=y2;
        };
        y=Suma/Sumb;
        x+=inc;
        Area+=(y)*inc;
        } while (x<=xmax);
        cout << "\n Integral=" << setprecision(12) << Area;
        cout << "\n Press 1 then enter to rerun or press 0 and enter to quit. \n";
        cin >> k;
    } while (k==1);
    return 0;
}

I understand almost all of it but I lack a good understanding of the operation of stringstream function. I was wondering if someone could assist me in finding where I've gone wrong and helping me to correct it.

The input format is: 1x^2+1x^1+1x^0 and it goes on like that.
I have several commented lines of code which I was using for debugging purposes. If anyone could lend a helping hand I'd be grateful because I can't figure out where I went wrong. If you could explain where I went wrong rather than give a corrected code it would be great since it would help me to hone my c++ skills and knowledge.

Cheers!

Microno

I doubt you're going to find anyone to help you with this code because your description of what it's supposed to do is so unclear. To begin, (x^2+x)/(x^2+x^3) isn't a polynomial; so your claim that your program finds the integral of a polynomial is not correct. Therefore, we don't actually know what this program is supposed to do, or how it is supposed to work.

May I suggest that you start by taking some small part of the program and isolating the code that does just that part. Then determine whether the code is doing what you expect it to do. If it isn't, then write a short, accurate description of what the program is supposed to do, along with another description of what it is doing, and post those descriptions along with the code. If your code is more like 15-20 lines instead of the 113 lines you posted, you'll be much more likely to get someone to look at it.

Also, if you don't understand stringstream there are two avenues:
1) Don't use stringstream
2) Learn how stringstream works by writing a bunch of test programs that will teach you various aspects of it.

Also your formatting needs a lot of work. You code is almot impossible to read and follow. See this.

Note how much easier this is to read:

    do {
        Suma = 0;
        Sumb = 0;
        cout << "\n" << "What is the numerator? \n";
        cin >> numerator;                           //Input for the numerator
        cout << "\n" << "What is the denominator? \n";
        cin >> denominator;                         //Input for the denominator
        /*cout << "How many plus signs exist in the numerator? \n";
        cin >> re;                                  //Input for number of plus signs*/
        cout << "What is the lower boundary? \n";
        cin >> xmin;                                //The lower boundary
        cout << "What is the upper boundary? \n";
        cin >> xmax;                                //The upper boundary
        cout << "In what increments do you wish to integrate? \n";
        cin >> inc;                                 //Steps between each calculation, increases calculation time
        string term = "000x^000";                   //Test term
        x = xmin;                                   //Sets x to the first value
        xmax -= inc;                                //Prevents inaccuracy due to the upper boundary
        TurnPlusesToSpaces (numerator);             //Calls earlier function
        //cout << numerator << "\n";                //Outputs the numerator
        stringstream ssa(numerator, stringstream::in | stringstream::out);
        //cout << terma << "\n";
        TurnPlusesToSpaces (denominator);           //Calls earlier function
        //cout << denominator << "\n";              //Outputs the numerator
        stringstream ssb(denominator, stringstream::in | stringstream::out);
        //cout << termb << "\n";
        do 
        {
            while (ssa >> terma) 
            {
                ParseTerm(terma, coeffn, expn);
                cout << coeffn << " " << expn << "\n";
                y1=fabs(f1(x, expn, coeffn));       //First y value
                //cout << y1;
                Sumb+=y2;
            };
            while (ssb >> termb) 
            {
                ParseTerm(termb, coeffd, expd);
                cout << coeffd << " " << expd << "\n";
                y2=fabs(f1(x, expd, coeffd));       //First y value
                                                    //cout << y2;
                Sumb+=y2;
            };
            y=Suma/Sumb;
            x+=inc;
            Area+=(y)*inc;
        } while (x<=xmax);
        cout << "\n Integral=" << setprecision(12) << Area;
        cout << "\n Press 1 then enter to rerun or press 0 and enter to quit. \n";
        cin >> k;
    } while (k==1);

Edited 4 Years Ago by WaltP

Your code is a little mystifying since it's incomplete (how can you solve a polynomial when you're throwing out the "+" and "-" and not storing that information anywhere?) but I assume you intend to put that functionality in later. But anyway, if your TurnPlustoSpace works, from:
"3X^2+x"
you get:
"3X^2 x"
You then send that string to stringstream ssa (why are you doing this by the way?), so ssa now holds in its buffer:
"3x^2" "x"

I think I see one problem with the next step where your stringstream usage on this line:
while (ssa >> terma) {

so now terma holds "3x^2x" --so now ParseTerm turns x^ into a space, so now you have "3 2x" which you then use stringstream to put "3" into coefficient and "2x" into exponent, which might be the error you're encountering. So really turning numerator into ssa screwed you since it eliminated the space between 2 and x. Try just sending numerator to ParseTerm after TurnPlustoSpace and see if you get anything useful from that. So your usage of stringstream is a little off. My advice is to use stringstream only to convert strings to ints/floats, which is otherwise tedious to convert manually, and use the string class member functions to do everything else.

Ok, I've been through the code and came to the conclusion that in order to provide greater clarity in terms of reading the code like WaltP said and to provide greater accuracy like Greywolf pointed out I made several changes in both the layout and the code itself.

Now the input is of the form: 1x^2+-1x^3+1x^4+1x^0

This allows both the negative number to be maintained and prevents any errors in the final result due to a dropped "-" sign. Furthermore I've revised the code as such and have ended up running a much more disturbing issue in that the final result fluctuates greatly depending on the increments used and whether or not the denominator is involved as a base value of one. So basically it gives me values far off depending on whether or not a denominator of one is used.

This is a bit of a problem. I've put the code here in case someone can actually see what's going on and why it's going crazy. I also placed the stringstream ssa(numerator, stringstream::in, stringstream::out) within the loop since ssa wasn't being reset to the value it needs to have in order to function properly. This solved an earlier problem and I don't know if it's directly related to the flawed value at the end but I suspect it isn't since this fixed an earlier flawed value issue I had after I'd revised the code.

Here is the code:

#include <iostream>
#include <sstream>
#include <string>
#include <math.h>
#include <iomanip>

using namespace std;
double f1(double a, double b, double e) //My function for the y values
{
    double y, h;
    h=(powf(a, b));                     //x term
    y=(e)*(h);                          //numerator for the function
    return (y);
}

void ParseTerm(string term, double& coeff, double& exp)
{
    const string TOKEN = "x^";                                          //The term to replace
    const int TOKEN_LENGTH = TOKEN.length();                            //The length of the search term
    const int index = term.find(TOKEN);                                 //Finds the term in the string and writes the position as an integer
    term.replace(index, TOKEN_LENGTH, " ");                             //Replaces the term at position index with a space
    stringstream ss (term, stringstream::in | stringstream::out);       //The non-spaced characters in the string are designated ss
    ss >> coeff;                                                        //Outputs the preceding number in the stream as the coefficient
    ss >> exp;                                                          //Outputs the following number in the stream as the exponent
}

void TurnPlusesToSpaces (string& equation)
{
    int foundp;
    foundp = equation.find("+");
    while (foundp != -1 )
        {
            const string TOKENA = "+";                                  //The term to replace
            const int TOKENA_LENGTH = TOKENA.length();                  //The length of the search term
            int indexa = equation.find(TOKENA);                         //Outputs the position of the term as an integer
            if (indexa != -1)
                {
                    equation.replace(indexa, TOKENA_LENGTH, " ");       //Replaces the term with a space in the string equation
                }
            foundp = equation.find("+");
            //cout << foundp << "\n";
            //cout << equation << "\n";
        }
}

int main()
{
    double coeffn, expn, coeffd, expd, Suma, Sumb, xmin, xmax, x, inc, y1, y2, y, Area; //Declaration of essential variables
    int k;
    k = 1;
    string terma, termb;
    string numerator = "1x^2+1x^3+-1x^8";                                //Declaration of the string for the numerator
    string denominator = "-1x^0";
    do {
        Suma = 0;
        Sumb = 0;
        inc = 0.01;
        xmin = 0.1;
        xmax = 0.8;
        /*cout << "\n" << "What is the numerator? \n";
        cin >> numerator;                                               //Input for the numerator
        cout << "\n" << "What is the denominator? \n";
        cin >> denominator;                                             //Input for the denominator
        cout << "What is the lower boundary? \n";
        cin >> xmin;                                                    //The lower boundary
        cout << "What is the upper boundary? \n";
        cin >> xmax;                                                    //The upper boundary
        cout << "In what increments do you wish to integrate? \n";
        cin >> inc;*/                                                     //Steps between each calculation, increases calculation time
        string term = "000x^000";                                       //Test term
        x = xmin;                                                       //Sets x to the first value
        xmax -= inc;                                                    //Prevents inaccuracy due to the upper boundary
        TurnPlusesToSpaces (numerator);                                 //Calls earlier function
        TurnPlusesToSpaces (denominator);                               //Calls earlier function
        //stringstream ssa(numerator, stringstream::in | stringstream::out);
        //stringstream ssb(denominator, stringstream::in | stringstream::out);
        //cout << numerator << "\n";                                    //Outputs the numerator
        //cout << terma << "\n";
        //cout << denominator << "\n";                                  //Outputs the denominator
        //cout << termb << "\n";
        do
        {
            stringstream ssa(numerator, stringstream::in | stringstream::out);
            while (ssa >> terma)
            {
                //cout << terma << "\n";
                ParseTerm(terma, coeffn, expn);
                //cout << coeffn << " " << expn << "\n";
                y1 = f1(x, expn, coeffn);                               //First y value
                //cout << y1 << "\n";
                Suma += y1;
            };
            //cout << Suma << "\n";
            stringstream ssb(denominator, stringstream::in | stringstream::out);
            while (ssb >> termb)
            {
                ParseTerm(termb, coeffd, expd);
                //cout << coeffd << " " << expd << "\n";
                y2 = f1(x, expd, coeffd);                               //First y value
                cout << y2 << "\n";
                Sumb += y2;
                cout << Sumb << "\n";
            };
            //cout << Sumb << "\n";
            y = Suma/Sumb;
            //cout << y << "\n";
            x += inc;
            //cout << x << "\n";
            Area += y*inc;
            //cout << Area << "\n";
        } while (x <= xmax);
        cout << "\n Integral=" << setprecision(12) << Area;
        cout << "\n Press 1 then enter to rerun or press 0 and enter to quit. \n";
        cin >> k;
    } while (k==1);
    return 0;
}

Cheers!
Microno

I think you should re-evaluate your approach to parsing the equation. It would be greatly simplified and more understandable if you take a more object-oriented approach. If you don't know how to use classes in C++, look it up; it's really useful :)

So, a polynomial is a collection of terms, but I don't think you've correctly realised what constitutes a "term" in a polynomial. Consider a polynomial like

1+x-3x^2+x^3

So, term consists of exactly three parts:

  • Coefficient
  • Variable
  • Exponent

In some cases, any or all of them might be present. If I separate the terms in brackets, you can see what they are in the example above:

(+1x^0)(+1x^1)(-3x^2)(+1x^3)

The variable value can change and only gets a definite value when we want to evaluate the polynomial at a point, so you don't really need to store that (unless your polynomial has more than one variable, like in a polynomial surface). So, what you might find useful is to make a PolynomialTerm structure that holds the coefficient and the exponent

class PolynomialTerm
{
public :
    double coefficient;
    double exponent;
};

You can then store these in a second class that contains a vector of terms:

class Polynomial
{
public :
    std::vector< PolynomialTerm > terms;
};

To make things easier, you could give the PolynomialTerm class an Evaluate method, that takes a double for the value that you want to evaluate the term at and returns whatever the term evaluates to at that value:

class PolynomialTerm
{
public :
    double coefficient;
    double exponent;

    double Evaluate( double x ) const { return coefficient * std::pow( x, exponent ); }
};

You could then add a similar method to the Polynomial class, which just sums all the term values:

 class Polynomial
{
public :
    std::vector< PolynomialTerm > terms;

    double Evaluate( double x ) const
    {
        double out = 0.0;
        for ( int i = 0; i < terms.size(); ++i )
            out += terms[i].Evaluate( x );   // Evaluate each term at x

        return out;   // Return the sum of the terms
    }
};

So, now you can write nice, understandable things in your code like:

double value = myPolynomial.Evaluate( 3.0 );

And get the value of you equation at a given x-value.

Where this approach would really start to simplify your program would be in the parsing of the equation. Using this approach, you would add a Parse method (or whatever you want to call it) to Polynomial and it would be responsible for taking a string and splitting it up on the + and - characters (don't throw them away though, you'll need them for the coefficients). Each time it splits off another section of the string, it would then know that that part of the string is a single term. You would then pass this sub-string to PolynomialTerm's Parse method and then that would be able to make sense of a string, spliting the term into coefficients (some of which could be negative) and exponents (all integers >= 0).

I'm sorry that doesn't directly answer your question, but I think it would be faster and easier for you to re-write your program like this that carrying on hacking away at what you have!

Have fun :)

This article has been dead for over six months. Start a new discussion instead.