Why my operator* acts illogical?

Pages: 12
@AbstractionAnon

5) You're ordering the list in ascending order by degree. That's fine, but you might want to consider the impact on print(). print() is going to print the smallest degree first.


How cab I change it? if I put
1
2
3
4
5
6
7
8
9
10
if (it->deg > term.deg)  //instead of (it->deg < term.deg
			{
				m_Polynomial.insert(it, term);
			}
			if (it->deg == term.deg)
			{
				it->cof += term.cof;
			}
		}
	m_Polynomial.push_front(term);     //instead of m_Polynomial.push_back(term); 


Does it work?


Can you please check? I tried to do your corrections:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;
#include "CPolynomial.h"


CPolynomial::CPolynomial()
{
	Node term;
	term.cof = 0;
	term.deg = 0; 
	AddOneTerm(term);
}

CPolynomial::CPolynomial(const string& file)
{
	ReadFromFile(file);
}

CPolynomial::CPolynomial(double *cof, int *deg, int n)
{
	std::list<Node>::iterator it = m_Polynomial.begin();

	for (unsigned int i = 0; i < n;i++)
	{
		Node term;

		term.cof = *cof;
		term.deg = *deg;

		AddOneTerm(term);
	}
}

CPolynomial::CPolynomial(const vector<double>& cof, const  vector<int> & deg)
{
	if (cof.size() != deg.size())
	{
		cerr << "Invalidate input!" << endl;
	}
	else
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		for (unsigned int i = 0; i < cof.size(); i++)
		{
			Node term;

			term.cof = cof[i];
			term.deg = deg[i];

			AddOneTerm(term);
		}
		}
	}

CPolynomial::~CPolynomial()
{

	m_Polynomial.clear();
}

CPolynomial CPolynomial:: operator+(const CPolynomial &right)
{
	list<Node>::iterator it = m_Polynomial.begin();
	list<Node>::iterator itR = right.m_Polynomial.begin(); //how should I define it for right??

	Node term;
	Node termR;

	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		term = *it;
		for (unsigned int j = 0; j < right.m_Polynomial.size(); i++)
		{
			termR = *itR;

			if (it->deg == itR->deg)
			{
				it->cof += itR->cof;
			}
			else
			{
				AddOneTerm(termR);
			}
		}
	}
}

CPolynomial CPolynomial:: operator-(const CPolynomial &right)
{
	list<Node>::iterator it = m_Polynomial.begin();
	list<Node>::iterator itR = right.m_Polynomial.begin(); //how should I define it for right??

	Node term;
	Node termR;

	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		term = *it;
		for (unsigned int j = 0; j < right.m_Polynomial.size(); i++)
		{
			termR = *itR;

			if (it->deg == itR->deg)
			{
				it->cof -= itR->cof;
			}
			else
			{
				termR.cof = -termR.cof;
				AddOneTerm(termR);
			}
		}
	}
}

CPolynomial CPolynomial:: operator*(const CPolynomial &right)
{
	Node temp;

	list<Node>::iterator it = m_Polynomial.begin();
	list<Node>::iterator itR = right.m_Polynomial.begin(); //how should I define it for right??

	Node term;
	Node termR;

	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		term = *it;
		for (unsigned int j = 0; j < right.m_Polynomial.size(); i++)
		{
			termR = *itR;

			if (it->deg == itR->deg && it->deg == 0)
			{
				// Skip
			}
			if (it->cof == 0 || itR->cof == 0)
			{
				//skip
			}
			else
			{
				temp.cof = term.cof*termR.cof;
				temp.deg = term.deg + termR.deg;

				AddOneTerm(temp);
			}
		}
	}
}

CPolynomial CPolynomial:: &operator=(const CPolynomial &right)
{
	this->m_Polynominal = right.m_Polynominal;
	return *this;
}


void CPolynomial::Print() const
{
	list<Node>::iterator it = m_Polynomial.begin();
	Node term;

	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		term = *it;

		if (term.cof == 0)
		{  
			;
		}
		else
		{
			if (term.cof > 0)
				cout << "+";
			cout << term.cof;
			if (term.deg != 0)
				cout << "x^" << term.deg;
		}
	}
	cout << endl;
}

void CPolynomial::ReadFromFile(string file)
{
	
	fstream MyFile;
	string p;
	int num;
	Node term;


	MyFile.open(file);
	if (!MyFile.is_open())
	{
		cout << "Unable to open input file" << endl;
		exit(EXIT_FAILURE);
	}
	MyFile >> p >> num;
	cout << "p=" << num;
	for (int i = 0; i < num; i++)
	{
		MyFile >> term.deg >> term.cof;
		AddOneTerm(term);
	}
}

void CPolynomial::AddOneTerm(Node term)
{
	std::list<Node>::iterator it = m_Polynomial.begin();
	

	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		term = *it;

		if (it->deg < term.deg)
		{
			m_Polynomial.insert(it, term);
		}
		if (it->deg == term.deg)
		{
			it->cof += term.cof;
		}
	}
	m_Polynomial.push_back(term);
}


And this is main file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;
#include "CPolynomial.h"


int main()
{
CPolynomial p1("P3.txt");
CPolynomial p2("P4.txt");
CPolynomial p3;
p1.Print();
p2.Print();

p3=p1+p2;
p3.Print();
p3=p1-p2;
p3.Print();

p3=p1*p2;
p3.Print();

return 0;
}
Last edited on
Your changes look fine for ordering the list in descending order. I might have left the list is ascending order and printed in reverse order, but either way works.

operators
---------
You're mixing idioms using a counter based for loop and iterators. As a consequence, you never advance your iterators. it and itR continue to point to the first element of the list.

I would use iterator based for loops.
1
2
3
4
for (it=m_Polynomial.begin(); it!=m_Polynomial.end(); it++)
{
  for (itR=right.m_Polynomial.begin(); itR!=right.m_Polynomial.end(); it++)
  {


line 81,114,151: if the degrees don't match, you add the right hand side term. This is going to result in adding every right hand side term every time through the outer loop (except when the degrees match). not what you want to do.

Print()
-------
Line 218: Same comment about mixing idioms with counter based for loop. You never advance your iterator.

Line 220: You're assigning the node the iterator points to to the term that was passed, wiping out the term that was passed. Remove this line.

Would you mind posting p3.txt and p4.txt?
Do you know the expected output for p3.txt and p4.txt?
Last edited on
@AbstractionAnon

Thanks for tips

p3.txt
1
2
3
P 2
1 2
4 -3


f(x)= 2x^1-3x^4

1
2
3
P 2
1 4
4 -3


f(x)= 4x^1-3x^4

I am just seeing the expected style (it's descending order)
But I have more txt files which should mean I should consider every case.

If you run the program, you see just P1 and P2 prints but program doesn't continue to run. Not sure why

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;
#include "CPolynomial.h"


CPolynomial::CPolynomial()
{
	Node term;
	term.cof = 0;
	term.deg = 0; 
	AddOneTerm(term);
}

CPolynomial::CPolynomial(const string& file)
{
	ReadFromFile(file);
}

CPolynomial::CPolynomial(double *cof, int *deg, int n)
{
	std::list<Node>::iterator it = m_Polynomial.begin();

	for (int i = 0; i < n;i++)
	{
		Node term;

		term.cof = *cof;
		term.deg = *deg;

		AddOneTerm(term);
	}
}

CPolynomial::CPolynomial(const vector<double>& cof, const  vector<int> & deg)
{
	if (cof.size() != deg.size())
	{
		cerr << "Invalidate input!" << endl;
	}
	else
	{
		std::list<Node>::iterator it = m_Polynomial.begin();

		for (unsigned int i = 0; i < cof.size(); i++)
		{
			Node term;

			term.cof = cof[i];
			term.deg = deg[i];

			AddOneTerm(term);
		}
		}
	}

CPolynomial::~CPolynomial()
{

	m_Polynomial.clear();
}

CPolynomial CPolynomial:: operator+(const CPolynomial &right)
{
	CPolynomial result(right);

	const list<Node>& terms = m_Polynomial;

	// for each term, add it to the result.
	for (list<Node>::const_iterator it = terms.begin(); it != terms.end(); ++it)
	{
		result.AddOneTerm(*it);
	}
	return result;
}
/*{
	CPolynomial result(right);

	list<Node>::iterator it = m_Polynomial.begin();
	list<Node>::iterator itR = m_Polynomial.begin();

	for (it == m_Polynomial.begin(); it != m_Polynomial.end(); it++)
	{
		for (itR == right.m_Polynomial.begin(); itR != right.m_Polynomial.end(); itR++)
		{

			if (it->deg == itR->deg)
			{
				it->cof = it->cof + itR->cof;
				it->deg = itR->deg;

				itR->cof = 0;
			}
			else
			{
				;
			}
			result.AddOneTerm(*it);
		}
	}
	return result;
}
*/
CPolynomial CPolynomial:: operator-(const CPolynomial &right)
{

	CPolynomial result(right);

	list<Node>::iterator it = m_Polynomial.begin();
	list<Node>::iterator itR = m_Polynomial.begin();


	for (it == m_Polynomial.begin(); it != m_Polynomial.end(); it++)
	{
		for (itR == right.m_Polynomial.begin(); itR != right.m_Polynomial.end(); itR++)

		{

			if (it->deg == itR->deg)
			{
				it->cof = it->cof - itR->cof;
				it->deg = itR->deg;

				itR->cof = 0;
			}
			else
			{
				itR->cof = -itR->cof;
			}
			result.AddOneTerm(*it);
		}
	}
	return result;
}

CPolynomial CPolynomial:: operator*(const CPolynomial &right)
{
	CPolynomial result(right);

	list<Node>::iterator it = m_Polynomial.begin();
	list<Node>::iterator itR = m_Polynomial.begin();

	for (it == m_Polynomial.begin(); it != m_Polynomial.end(); it++)
	{
		for (itR == right.m_Polynomial.begin(); itR != right.m_Polynomial.end(); itR++)
		{
			if (it->cof == 0 || itR->cof == 0)
			{
				;
			}
			else
			{
				itR->cof = (it->cof)*(itR->cof);
				itR->deg = it->deg + itR->deg;

				result.AddOneTerm(*it);
			}
		}
	}
	return result;
}

CPolynomial& CPolynomial:: operator=(const CPolynomial &right) 
{

	this->m_Polynomial = right.m_Polynomial;
	return *this;
}


void CPolynomial::Print() const
	{

		list<Node>::const_iterator it;
		
		for (it = m_Polynomial.begin(); it != m_Polynomial.end(); it++)
		{ 

			if (it->cof == 0)
			{  
				;
			}
			else
			{
				if (it->cof > 0)
					cout << "+";
				cout << it->cof;
				if (it->deg != 0)
					cout << "x^" << it->deg;
			}
		}
		cout << endl;
	}

void CPolynomial::ReadFromFile(string file)
{
	Node term;
	fstream MyFile;
	string p;
	int num;

	MyFile.open(file);

	if (!MyFile.is_open())
	{
		cerr << "Unable to open input file" << endl;
		exit(EXIT_FAILURE);
	}
	else
	{
		MyFile >> p >> num;

		std::list<Node>::iterator it = m_Polynomial.begin();

		for (int i = 0; i < num; i++)
		{
			MyFile >> term.deg >> term.cof;
		
			m_Polynomial.push_back(term);
		}
		MyFile.close();
	}

}

void CPolynomial::AddOneTerm(Node term)
{
	std::list<Node>::iterator it = m_Polynomial.begin();
	
	for (unsigned int i = 0; i < m_Polynomial.size(); i++)
	{
		if (it->deg < term.deg)
		{
			m_Polynomial.insert(it, term);
		}
		if (it->deg == term.deg)
		{
			it->cof += term.cof;
		}
	}
	m_Polynomial.push_back(term);
}
Last edited on
Output:

p = 2
check:2 1
check:2 1
Last edited on
I am sorry, but why I don't want it?
if degrees are same, add coefficients; if not just add the term (with a different deg)


This doesn't accurately describe what you're doing. The worst thing you're doing is not returning a value, but you are also modifying *this in a function that should logically be const.

I would expect the operator to look more like this:

1
2
3
4
5
6
7
// I've taken the liberty of changing the method signature to simplify things.
CPolynomial CPolynomial:: operator+(CPolynomial right) const
{
    for (auto node : m_Polynomial) right.AddOneTerm(node);

    return right;
}


If AddOneTerm already does what you want, don't duplicate the code.

Forgive the use of auto and the ranged-for if you're stuck with something pre-C++11.
Thank you for helping @cire

I am not allowed to change .h file

but I changed it, added return, didn't modify this
Is it fine?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

CPolynomial CPolynomial:: operator+(const CPolynomial &right)
{

	list<Node>::iterator it = m_Polynomial.begin();
	list<Node>::iterator itR = m_Polynomial.begin();

	Node termR;
	Node temp;

	for (it == m_Polynomial.begin(); it != m_Polynomial.end(); it++)
	{
		for (itR == right.m_Polynomial.begin(); itR != right.m_Polynomial.end(); it++)
		
		{
			termR = *itR;

			if (it->deg == itR->deg)
			{
				temp.cof= it->cof+ itR->cof;
				temp.deg = it->deg;

				it->cof = 0;
			}
			else
			{
				temp.cof = termR.cof;
				temp.deg = itR->deg;
			}
			AddOneTerm(temp);
		}
	}
	return *this;
}
but I changed it, added return, didn't modify this
Is it fine?

No. AddOneTerm modifies *this, and again you are duplicating code from AddOneTerm.

1
2
3
4
5
6
7
8
9
10
11
12
13
CPolynomial CPolynomial:: operator+(const CPolynomial &right)
{
    CPolynomial result(right);   // make result a copy of right.

    // give our self a reference to a const list so we don't accidentally modify it.
    const list<Node>& terms = m_Polynomial;

    // for each term, add it to the result.
    for (list<Node>::const_iterator it=terms.begin(); it != terms.end(); ++it)
        result.AddOneTerm(*it);

    return result;
}


The one caveat is that AddOneTerm will result in a term with a coefficient of 0 if ading a term to an existing returns results in such a thing. That may or may not be an issue depending on your requirements, but modifying AddOneTerm would be appropriate if it is an issue.



Last edited on
For operator- I thought about it but I get error or it->cof = -it->cof;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
	CPolynomial result(right);

	const list<Node>& terms = m_Polynomial;

	for (list<Node>::const_iterator it = terms.begin(); it != terms.end(); ++it)
	{
		it->cof = -it->cof;

		result.AddOneTerm(*it);
	}
	return result;
}


Can you please check my last comment (the very long one)? My program doesn't run well @cire
Last edited on
My code is almost done.
this is a minimal code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;


typedef struct Node
{
	double  cof;      // coefficient 
	int     deg;      // degree
} Node;

class CPolynomial
{
public:
	CPolynomial();
	CPolynomial(const string& file);
	~CPolynomial();
	CPolynomial operator*(const CPolynomial &right);
	CPolynomial& operator=(const CPolynomial &right);
	void Print() const;

private:
	void ReadFromFile(string file);
	void AddOneTerm(Node term);

private:
	list<Node> m_Polynomial;
};



int main()
{
	CPolynomial p1("P3.txt");
	CPolynomial p2("P4.txt");
	CPolynomial p3;
	p1.Print();
	p2.Print();

	p3 = p1*p2;
	p3.Print();

	system("pause");
	return 0;
}

CPolynomial::CPolynomial()
{
	Node term;
	term.cof = 0;
	term.deg = 0;
	AddOneTerm(term);
}

CPolynomial::~CPolynomial()
{
	m_Polynomial.clear();
}

CPolynomial::CPolynomial(const string& file)
{
	ReadFromFile(file);
}

CPolynomial CPolynomial:: operator*(const CPolynomial &right)
{
	CPolynomial result;

	result.m_Polynomial = m_Polynomial;

	Node term;
	Node termR;
	Node temp;
	for (list<Node>::const_iterator it = m_Polynomial.begin(); it != m_Polynomial.end(); ++it)
	{
		for (list<Node>::const_iterator itR = right.m_Polynomial.begin(); itR != right.m_Polynomial.end(); ++itR)
		{
			term = *it;
			termR = *itR;

			temp.cof = termR.cof* term.cof;
			temp.deg = termR.deg + term.deg;

			cout << temp.cof << "x^" << temp.deg << endl;

			result.AddOneTerm(term);
		}
	}
	return result;
}

CPolynomial& CPolynomial:: operator=(const CPolynomial &right)
{

	this->m_Polynomial = right.m_Polynomial;
	return *this;
}

void CPolynomial::Print() const
{
	list<Node>::const_iterator it;

	for (it = m_Polynomial.begin(); it != m_Polynomial.end(); it++)
	{
		if (it->cof == 0)
		{
			;
		}
		else
		{
			if (it->cof > 0)
			{
				if (it != m_Polynomial.begin()) // if 'it' is not the first term, '+' is not necessary
					cout << "+";
			}
			cout << it->cof;
			if (it->deg != 0)
				cout << "x^" << it->deg;
		}
	}
	cout << endl;
}

void CPolynomial::ReadFromFile(string file)
{
	Node term;
	fstream MyFile;
	string p;
	int num;

	MyFile.open(file);

	if (!MyFile.is_open())
	{
		cerr << "Unable to open input file" << endl;
		exit(EXIT_FAILURE);
	}
	else
	{
		MyFile >> p >> num;

		std::list<Node>::iterator it = m_Polynomial.begin();

		for (int i = 0; i < num; i++)
		{
			MyFile >> term.deg >> term.cof;

			m_Polynomial.push_back(term);
		}
		MyFile.close();
	}

}

void CPolynomial::AddOneTerm(Node term)
{
	std::list<Node>::iterator it;
	for (it = m_Polynomial.begin(); it != m_Polynomial.end();)
	{
		if (term.deg < it->deg)
		{
			++it;
			continue;
		}
		else if (term.deg == it->deg) // if degree is same, coefficient is added directly 
		{
			it->cof += term.cof;
			return;
		}
		else // if the added degree is big than current term of m_polynomial,
			// justify the relationship of degree with the next term
			// if smaller than next, then 'insert'
			// if equal to the next term, then add the cof to next term
		{
			std::list<Node>::iterator next_it;
			next_it = ++it;
			if (next_it != m_Polynomial.end())
			{
				if (term.deg < it->deg)
				{
					m_Polynomial.insert(next_it, term);
					return;
				}
				else
				{
					it->cof += term.cof;
					return;
				}
			}
			else
			{
				m_Polynomial.push_back(term);
			}
			return;
		}
	}

}


output:

1
2
3
4
5
6
7
2x^1-3x^4     (P1)
4x^1-3x^4     (P2)
8x^2             ( term.cof  termR.cof  temp.cof)
-6x^5            ( term.cof  termR.cof  temp.cof)
-12x^5          ( term.cof  termR.cof  temp.cof)
9x^8             ( term.cof  termR.cof  temp.cof)
6x^1-9x^4    (P1*P2)
Last edited on
Topic archived. No new replies allowed.
Pages: 12