I have a polynomial of the type std::vector<T>
and a matrix of the type std::vector<std::vector<T>>
, with classes for both of them. The output (in my case void print()-function) for each of those classes works fine. Now I created a matrix consisting of multiple polynomials, like this , and I'm not entirely sure how to create an output for it.
Suppose I have a polynomial p1: Polynomial<T> p1{0,1,2}
. My Polynomial::print function interprets it correctly and returns: x^2+x+1
. For a 'normal' matrix of the type Matrix<T> m1(2,2,0)
, a 2x2-matrix filled with 0's, it is correctly returned with Matrix::print() as well as:
0, 0
0, 0
Now, suppose I want a polynomial matrix m1: Matrix<Polynomial<T>> mp(2,2,p1)
, a 2x2-matrix filled polynomial p1 from before. The code is accepted, but now I want to print the matrix using matrix::print(), so that I get:
x^2+x+1, x^2+x+1
x^2+x+1, x^2+x+1
Minimal working example:
#include<iostream>
#include<vector>
using namespace std;
template <typename T>
class Polynomial;
template <typename T>
class Matrix
{
public:
Matrix(std::vector<std::vector<T> > ma);
Matrix(int rows, int cols, T const & init);
Matrix(const Matrix & m);
~Matrix();
Matrix ();
void print();
friend void Polynomial<T>::print();
private:
std::vector<std::vector<T>> Ma;
};
template <typename T>
Matrix<T>::Matrix(std::vector<std::vector<T>> ma)
:Ma(ma)
{}
template <typename T>
Matrix<T>::Matrix(int rows, int cols, T const & init)
{
std::vector<std::vector<T>> b(rows, std::vector<T>(cols, init));
Ma=b;
}
template <typename T>
Matrix<T>::~Matrix()
{}
template <typename T>
Matrix<T>::Matrix() :
Matrix(1,1,0)
{}
template <typename T>
Matrix<T>::Matrix(const Matrix & m)
{
Ma = m.Ma;
}
template <typename T>
void Matrix<T>::print()
{
for (auto i = 0; i < Ma.size(); i++)
{
for (auto j = 0; j < Ma[i].size(); j++)
if ( j == Ma.size()-1 )
{
cout << Ma[i][j]; //This causes problems
}
else
cout << Ma[i][j] << ", \t";
cout << endl;
}
}
template <typename T>
class Polynomial
{
public:
Polynomial(std::vector<T> const& coef);
Polynomial(std::initializer_list<T> const& coef);
void print();
const int getdeg();
const T getKoeff(int index) const;
friend class Matrix<T>;
Polynomial ();
friend void print();
private:
std::vector<T> coefficient;
};
template <typename T>
Polynomial<T>::Polynomial(std::vector<T> const& coef) :
coefficient(coef)
{}
template <typename T>
Polynomial<T>::Polynomial(std::initializer_list<T> const& coef) :
coefficient(coef)
{}
template <typename T>
Polynomial<T>::Polynomial ()
{
coefficient = new std::vector<T> [coefficient.getdeg()];
coefficient[0]=0;
}
template <typename T>
void Polynomial<T>::print() //Reduced version for demonstration purposes, but
{
for ( int i = getdeg(); i >= 0; i-- )
{
cout << coefficient[i] << "x^" << i; //the output is always of the type cout << xyz
}
}
template <typename T>
const int Polynomial<T>::getdeg()
{
int g = coefficient.size()-1;
return g;
}
int main()
{
typedef double T;
Polynomial<T> p1{0,1,2};
p1.print();
Matrix<Polynomial<T>> mp(2, 3, Polynomial<T>{0});
// mp.print(); //When this is commented out chaos ensues
return 0;
}
2x^21x^10
is returned (Note: +&- excluded from the notation, since the code would be too long).
The matrix::print() might cause problems due to cout
having problems handling the result of the polynomial. Anybody have an idea how to make matrix::print() give useful results for a polynomial matrix? Thank you in advance.
In Matrix<T>::print()
you are trying to call
cout << Ma[i][j];
and when Ma[i][j]
is a Polynomial<double>
, there is no matching overload for the output operator. You could call Ma[i][j].print()
instead, but then your Matrix
wont work for int
. Long story short : Instead of writing your own print()
you better overload operator<<(std::ostream&,const T&)
for your types.
For Polynomial
that would be something along the line of (I allowed myself to strip your code down quite a bit and to add the "+"):
#include<iostream>
#include<vector>
template <typename T> struct Polynomial { std::vector<T> data; };
template <typename T>
std::ostream& operator<<(std::ostream& o,const Polynomial<T>& pol) {
auto power = [](int n){
return (n==0) ? "" : (n==1) ? "x" : "x^" + std::to_string(n);
};
auto sign = [&](int i){
return (pol.data[i]<0 || i==pol.data.size()-1) ? "" : "+";
};
// DO THIS ONLY AT HOME !!! --------v
for (size_t i = pol.data.size()-1; i < pol.data.size(); i-- ) {
o << sign(i) << pol.data[i] << power(i);
}
return o;
}
int main() {
Polynomial<double> p1{{0,1,2,-3,4}};
std::cout << p1 << "\n";
}
Prints
4x^4-3x^3+2x^2+1x+0
You dont need to write desctructors/constructors that the compiler can write for you. Actually it doesnt need any constructor as long at is just a bare std::vector
in disguise. Note that I tried to keep it short, but not necessarily clean, for example I would never rely on unsigned overflow for a loop condition in any serious code, and heavy use of the ternary doesnt really boost readability. However, I am serious about using lambdas . They help to keep stuff localized. I'll leave it to you to print nothing for the last coefficient in case it is 0
;).
To print rows of the matrix you could provide an overload for std::vector<T>
, that would be something along the line of:
template <typename T> struct Matrix {
using element_type = T;
using row_type = std::vector<element_type> ;
using data_type = std::vector<row_type> ;
Matrix(int rows, int cols, T const & init) :
data(data_type(rows,row_type(cols,init)))
{}
data_type data;
};
template <typename T>
std::ostream& operator<<(std::ostream& o,const std::vector<T>& v) {
for (auto& x : v) o << x << "\t";
return o;
}
template <typename T>
std::ostream& operator<<(std::ostream& o,const Matrix<T>& mat) {
for (const auto& row : mat.data) o << row << "\n";
return o;
}
Now printing a matrix is as simple as this
int main() {
using Matrix = Matrix<Polynomial<double>>;
Polynomial<double> p1{{1,2}};
Matrix mp(2,3,p1);
std::cout << mp;
return 0;
}
Prints
2x+1 2x+1 2x+1
2x+1 2x+1 2x+1
See also here: https://ideone.com/n00bqn (is ideone trying to make fun of me or what? :)
You want to print content of Map[i][j]
(it is Polynomial<double>
) by using operator<<
but operator which takes as argument Polynomial<double>
is not defined. So you should add declaration
template<class U>
friend std::ostream& operator<<(std::ostream&,const Polynomial<U>&);
in your Polynomial
template and make definition outside class as
template<class T>
std::ostream& operator<<(std::ostream& out, const Polynomial<T>& poly)
{
poly.print();
return out;
}
then you can call
cout << Ma[i][j] << ", ";
in your Matrix<T>::print
method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.