Страница 1 из 3

класс полином

Добавлено: 02 ноя 2009, 13:11
inlaf
здравствуйте.
такая вот у меня наработка. есть траблы с перегрузкой оператора += , = , *= .
прошу помощи.

Код: Выделить всё

#include <iostream>
#include <iomanip>
#include <cmath>
#include <conio.h>
#include <windows.h>
#include "ConvOem.h"
using namespace std;

CConvOem szbuf(100);

class Vector;
class Polynom 
{
private:
	size_t m_Dim;	//размер
	double *m_Pol; 
public:
	Polynom();								// к-ор по умолчанию		
	Polynom(const size_t);					// к-ор с 1 аргументом
	Polynom(const size_t,const double* );	//конструктор с 2 аргументами
	Polynom(const Polynom&);				// Конструктор копирования
	~Polynom();								// Деструктор
	size_t GetDim() const {return m_Dim;}	// Получение степени
	//void SetDim(int y){ m_Dim = y; }		// Изменение Степени.
	double GetKof(const size_t i); //Получение i-ого коэффициента.
	void SetKof(const size_t i,const double x ); // Изменение i-ого коэффициента.
	void Show() const;
	friend Vector Vec2Poly(const Polynom &);
	friend Polynom Poly2Vec(const Vector &);


	Polynom operator+() {return *this;} //перегрузка унарного оператора "+"
	Polynom operator-(); //перегрузка унарного оператора "-"


	Polynom & operator=(Polynom &no); 
	Polynom & operator=(double no); 
	Polynom & operator+=(Polynom &no); 
	Polynom & operator+=(double no); 
	Polynom & operator-=(Polynom &no); 
	Polynom & operator-=(double no); 
	Polynom & operator*=(Polynom &no);
	Polynom & operator*=(double no);
	Polynom & operator/=(double no);
	Polynom & operator^=(double no);


};

class Vector
{  
private:
	size_t m_Dim;						// Размер вектора.
	double *m_pVec;						//адрес массива с координатами вектора
public:
	Vector(size_t,double*);				//конструктор с 1-им параметром
	Vector(size_t);						//конструктор с 2-мя параметром
	Vector();
	Vector(const Vector&);				//конструктор копирования
	~Vector();							// Деструктор.
	double GetKof(const size_t i); // Получение i-ой координаты.
	void SetKof(const size_t i, const double x);	// Изменение i-ой координаты.
	size_t GetDim() const {return m_Dim;}	// Получение размера вектора.
	void Show() const;	// Вывод вектора.
	friend Vector Vec2Poly(const Polynom &);
	friend Polynom Poly2Vec(const Vector &);
};

double Vector::GetKof(const size_t i)
{
	if (i > m_Dim)
	{
		cout<<szbuf.toOem("Неправильное значение")<<endl;;
		exit(-1);
	}
	return m_pVec[i-1];
}
void Vector::SetKof(const size_t i,const double x )
{
	if (i > m_Dim)
	{
		cout<<szbuf.toOem("Неправильное значение ")<<endl;
		exit(-1);
	}
	m_pVec[i-1]=x;
}

void Vector::Show() const
{
	cout << '(';
	size_t i;
	for (i = 0; i < m_Dim; ++i)
	{
		cout << m_pVec[i];
		if (i < m_Dim - 1) cout << ", ";
	}
	cout << ')' << endl;
}

Vector::Vector(const size_t Dim,double* pVec):m_Dim(Dim) // к-ор с 2мя арг
{
	m_pVec=new double[Dim];
	if (!m_pVec)
	{
		cout <<szbuf.toOemA( "Ошибка! Неверный размер вектора." )<< endl;
		exit(-3);
	}
	for(int i=0;i<m_Dim;i++)
		m_pVec[i]=pVec[i];
}
Vector::Vector(size_t Dim):m_Dim(Dim) // к-ор с 1им арг
{
	m_pVec= new double[m_Dim];
	if (!m_pVec)
	{
		cout <<szbuf.toOemA( "Ошибка! Неверный размер вектора." )<< endl;
		exit(-1);
	}
	for(int i=0;i<m_Dim;i++)
		m_pVec[i]=0.0;
}

Vector::Vector():m_Dim(1) // к-ор без арг
{ 
	m_pVec=new double [m_Dim];
	if(!m_pVec) {
		cout<<"Error"<<endl;
		exit (-1);
	}	
}

Vector::Vector(const Vector& cv):m_Dim(cv.m_Dim) //конструктор копирования
{
	if (!(m_pVec=new double[m_Dim]))
	{
		cout<<szbuf.toOemA("Нет памяти") <<endl;
		exit(-1);
	}
	//копирование координат
	size_t i;
	for(i=0;i<m_Dim;++i)
		m_pVec[i]=cv.m_pVec[i];
	cout<<szbuf.toOemA("копия создана Vec") <<endl;
}
Vector::~Vector()
{
	cout << szbuf.toOemA("Вектор успешно удалён ...") << endl;
	delete[] m_pVec;

}
Polynom Poly2Vec(const Vector& cv)
{
	Polynom c(cv.m_Dim-1);
	for(int i=0; i < cv.m_Dim; ++i)
		c.m_Pol[i]=cv.m_pVec[i];
	return c;
}
Vector Vec2Poly(const Polynom& cc)
{
	//создадим объект класса вектор
	Vector v(cc.m_Dim);
	for(int i=0; i<cc.m_Dim; ++i)
		v.m_pVec[i]=cc.m_Pol[i];
	return v;
}
double Polynom::GetKof(const size_t i)
{
	if (i > m_Dim)
	{
		cout<<szbuf.toOem("Неправильное значение")<<endl;;
		exit(-1);
	}
	return m_Pol[i-1];
}
void Polynom::SetKof(const size_t i,const double x )
{
	if (i > m_Dim)
	{
		cout<<szbuf.toOem("Неправильное значение ")<<endl;
		exit(-1);
	}
	m_Pol[i]=x;
}

Re: класс полином

Добавлено: 02 ноя 2009, 13:13
inlaf

Код: Выделить всё

//Конструктор без аргументов
Polynom::Polynom(): m_Dim(0) 
{	
	m_Dim=m_Dim+1;
	m_Pol=new double[m_Dim];    // Выделение памяти для Polynoma
	if(!m_Pol)
	{
		cout<<szbuf.toOem("Ошибка")<<endl;
		exit (-1);
	}	
	m_Pol[0]=0;
}
// Определение конструктора с 1 арг
Polynom::Polynom(const size_t Dim): m_Dim(Dim) 
{
	{
		m_Dim=Dim+1;
		if(!m_Dim)
		{
			cout<<szbuf.toOem("Ошибка")<<endl;
			exit (-3);
		}
		if(!(m_Pol= new double[m_Dim+1]))
		{
			cout<<szbuf.toOem("Ошибка")<<endl;
			exit (-1);
		}
		size_t i;
		for(i=0; i <= m_Dim; ++i)
		{
			m_Pol[i]=i;
		}

	}
}
Polynom::Polynom(const size_t Dim,const double *mas):m_Dim(Dim)
{
	m_Dim=Dim+1;
	if(!m_Dim)
	{
		cout<<szbuf.toOem("Неверный размер")<<endl;
		exit(-3);
	}
	if(!(m_Pol= new double[m_Dim+1]))
	{
		cout<<szbuf.toOem("Нет памяти")<<endl;
		exit(-1);
	}
	size_t i;
	if(mas)
	{
		for(i=0;i <= m_Dim; ++i)
		{
			m_Pol[i]=mas[i];
		}
	}

}
//Конструктор копирования 
Polynom::Polynom(const Polynom& Pol):m_Dim(Pol.m_Dim) 
{	
	if (!(m_Pol=new double[m_Dim+1]))
	{
		cout<<szbuf.toOem("Нет памяти") <<endl;
		exit(-1);
	}
	for (int i=0; i < m_Dim; i++)
		m_Pol[i]=Pol.m_Pol[i];
	cout<<szbuf.toOem("копия Pol создана") <<endl;
}

Polynom::~Polynom() 
{		
	cout << szbuf.toOem("Полином успешно удалён ...") << endl;
	delete[] m_Pol;
}

void Polynom::Show()const
{	

	size_t i;
	for(i=0;i <= m_Dim-1;++i)

		if (i != 0)

		{
			cout << m_Pol[i] << "*x^" << m_Dim-i-1;
			if(m_Pol[i]>=0)
				cout << "+";
		}
		//cout << m_pol[m_dim-1] << endl;
		cout << endl;
}

/*
size_t i;
for(i=0;i <= m_Dim-1;++i)
{
cout << m_Pol[i];
if (i !=0)
cout << "x^"<<m_Dim-1;
if
(m_Pol[i]>=0)
cout << "+";

}
//cout << m_Pol[m_Dim+1]<< endl;
cout << endl;
*/


Re: класс полином

Добавлено: 02 ноя 2009, 13:14
inlaf

Код: Выделить всё

//////////////////    OPERATORI   /////////////////////////
Polynom Polynom: :o perator-() 
{	
	size_t i;
	for (i=0; i<m_Dim; ++i)
		m_Pol[i] = -m_Pol[i];
	return *this;
}
Polynom & Polynom: :o perator=(Polynom & no)
{
	if ( this != &no)
	{
		delete[] m_Pol;
		if (!(m_Pol=new double[m_Dim=no.m_Dim]))
		{
			cout<<szbuf.toOem("Ошибка! Недостаточно памяти!")<<endl;;
			exit(-1);
		}
		size_t i;
		for (i=0; i < m_Dim; ++i)
			m_Pol[i]=no.m_Pol[i];
	}
	return *this;

}
Polynom & Polynom: :o perator=(double no) // Оператор присваивания, когда правая часть число
{
	size_t i;
	for (i=0; i <= m_Dim; ++i)
		m_Pol[i]=no;
	return *this;
}
Polynom & Polynom: :o perator+=(Polynom & no) // Оператор присваивания cо сложением
{
	size_t i,k,j;
	Polynom temp;

	if (m_Dim > no.m_Dim)
	{
		i = m_Dim;
		k=no.m_Dim;
	}
	else 
	{
		i = no.m_Dim;
		k = m_Dim;
	}

	temp.m_Pol = new double[i];

	for(j=0; j<k; ++j)
		temp.m_Pol[j] = m_Pol[j]+no.m_Pol[j];

	for(j=k; j<i; ++j)
		if (m_Dim > no.m_Dim)
			temp.m_Pol[j] = m_Pol[j];
		else   temp.m_Pol[j] = no.m_Pol[j];

		//	m_Pol[i]=temp.m_Pol[j];

		return *this;

		/*
		if (m_Dim>=no.m_Dim)
		{Polynom temp;
		temp.m_Pol=new double[m_Dim];
		for(int i=0;i<=m_Dim;i++)
		temp.m_Pol[i]=m_Pol[i]+no.m_Pol[i];
		return temp;
		}
		else //(m_Dim<no.m_Dim)
		{Polynom temp(no.m_Dim);
		for(int i=0;i<=no.m_Dim;i++)
		temp.m_Pol[i]=m_Pol[i]+no.m_Pol[i];
		return temp;
		}
		*/


}
Polynom & Polynom: :o perator+=(double no) // Оператор присваивания cо сложением, когда правая часть число.
{
	size_t i;
	for (i=0; i < m_Dim; ++i)
		m_Pol[i]+=no;
	return *this;
}
Polynom & Polynom: :o perator-=(Polynom & no) // Оператор присваивания c вычитанием
{
	if ( m_Dim!= no.m_Dim  )
	{
		cout<<szbuf.toOem("Ошибка! Недостаточно памяти!")<<endl;
		exit(-100);
	}
	size_t i;
	for(i=0; i<m_Dim; ++i)
		m_Pol[i] -= no.m_Pol[i];
	return *this;
}
Polynom & Polynom: :o perator-=(double no) // Оператор присваивания c вычитанием, когда правая часть число.
{
	size_t i;
	for (i=0; i < m_Dim; ++i)
		m_Pol[i]-=no;
	return *this;
}
Polynom & Polynom: :o perator*=(Polynom & no) //оператор присваивания с умножением
{	
	size_t i,j,k;
	Polynom temp;

	if (m_Dim > no.m_Dim)
	{
		i = m_Dim;
		k=no.m_Dim;
	}
	else 
	{
		i = no.m_Dim;
		k = m_Dim;
	}

	temp.m_Pol = new double[i];

	for(i=0;i<=m_Dim;++i)
	{
		for( j=0;j<=no.m_Dim;++j)
			temp.m_Pol[i+j]+=m_Pol[i]*no.m_Pol[j];
	}
	return *this;
	/*
	if (!(m_Pol[m_Dim = no.m_Dim]))
	{
	cout<<szbuf.toOem("Ошибка! Недостаточно памяти!")<<endl;
	exit(-1);
	}
	size_t i;
	for (i=0; i<m_Dim; ++i)
	m_Pol[i] *= no.m_Pol[i];
	return *this;
	*/
}
Polynom & Polynom: :o perator*=(double no) //для случая,когда правый операнд число
{
	size_t i;
	for(i=0; i<m_Dim; ++i)
		m_Pol[i] *= no;
	return *this;
}

Polynom & Polynom: :o perator^=(double no)//оператор возвидения в степень для случая,когда правый операнд число
{
	size_t i;
	for(i=0; i<m_Dim; ++i)
		m_Pol[i] = pow(m_Pol[i],no);
	return *this;
}

void main()
{	

	Polynom p1;
	Polynom p2(4);
	double mass[4]={4,5,6,7};
	Polynom p3(3,mass);
	p1.Show();
	p2.Show();
	p3.Show();
	Polynom p4(p3);
	p4.Show();
	p4.SetKof(3,20);
	p4.Show();
	double per;                                 
	per = p4.GetKof(3);
	cout << per << endl;



	double mass2[5]={-4,5,6,-0.77,0};
	Vector va3(5,mass2);
	va3.Show();
	Polynom toVec = Poly2Vec(va3);	
	Vector toPol = Vec2Poly(toVec);
	toVec.Show();
	toPol.Show();

	cout<<endl;

	cout <<szbuf.toOem("Использование оператора +:");
	+p1;
	p1.Show();
	cout <<szbuf.toOem("Использование оператора -:");
	-p1;
	p1.Show();

	cout<<endl;

	cout <<szbuf.toOem("Использование бинарного оператора =:");
	p1=p4;
	p1.Show();

	cout << szbuf.toOem("Использование бинарного оператора = когда правый операнд число(2):");
	double x=2;
	p1=x;
	p1.Show();

	cout <<szbuf.toOem("Использование бинарного оператора +=:");
	double mass3[]={1,1,1};
	Polynom p6(2,mass3);
	double mass4[]={4,3,100,100,30};
	Polynom p7(4,mass4);
	p6+=p7;
	p6.Show();

	cout << szbuf.toOem("Использование бинарного оператора += когда правый операнд число:");
	double y=3;
	p1+=y;
	p1.Show();

	cout <<szbuf.toOem("Использование бинарного оператора -=:");
	p1-=p4;
	p1.Show();

	cout << szbuf.toOem("Использование бинарного оператора -= когда правый операнд число:");
	double z=4;
	p1-=z;
	p1.Show();

	cout << szbuf.toOem("Использование бинарного оператора *:");
	p7*=p6;
	p7.Show();

	getch();

}

Re: класс полином

Добавлено: 02 ноя 2009, 14:25
Romeo
В операторе присваивания всё вроде честно, с первого взгляда. Оператор += я доработал.

Код: Выделить всё

Polynom & Polynom: :o perator+=(Polynom & no) // Оператор присваивания cо сложением
{
  if (&no != this)
  {
    size_t i,k,j;
 
    if (m_Dim > no.m_Dim)
    {
        i = m_Dim;
        k=no.m_Dim;
    }
    else 
    {
        i = no.m_Dim;
        k = m_Dim;
    }

    double* new_Pol = new double[i];

    for(j=0; j<k; ++j)
        new_Pol[j] = m_Pol[j]+no.m_Pol[j];

    for(j=k; j<i; ++j)
        if (m_Dim > no.m_Dim)
            new_Pol[j] = m_Pol[j];
        else
            new_Pol[j] = no.m_Pol[j];

    Clear();

    m_Pol = new_Pol;
    m_Dim = i;
  }
  return *this;
}
Clear - это то, что вызывается в деструкторе класса. В таких случаях все операторы в деструкторе выносят в отдельный метод (Clear), а в самом деструкторе оставляют вызов этого метода.

Re: класс полином

Добавлено: 02 ноя 2009, 18:40
inlaf
спасибо. но складывает неудачно, степени не учитываются. идет сложение поэлементно с 1ого.

перебрал конструктор Show.

Код: Выделить всё

void Polynom::Show()const
{	
	size_t i;
	for(i=0;i<m_Dim-1;++i)
	{
		cout << m_Pol[i] << "*x^" << m_Dim-i-1;
		if(m_Pol[i+1]>=0)
			cout << "+";
	}
	cout << m_Pol[m_Dim-1] << endl;
} 
посидел. ничего другого не пришло в голову.
бред

Код: Выделить всё

Polynom & Polynom: :o perator+=(Polynom & no) // Оператор присваивания cо сложением
{
	if (&no != this)
  {
    size_t i,k,j;
 
    if (m_Dim > no.m_Dim)
    {
        i = m_Dim;
        k=no.m_Dim;
    }
    else 
    {
        i = no.m_Dim;
        k = m_Dim;
    }

    double* new_Pol = new double[i];
	
	for (j=0; j<i; ++j)
		 new_Pol[j]=0;

	for(j=k; j<i; ++j)
        new_Pol[j] = new_Pol[j]+no.m_Pol[j];

    for(j=0; j<i-k; ++j)
        if (m_Dim > no.m_Dim)
            new_Pol[j] += m_Pol[j];
        else
	new_Pol[j] += no.m_Pol[j];

 void Clear();
    m_Pol = new_Pol;
    m_Dim = i;
  }
 return *this;
}
Romeo попробывал погуглить на тему Clear, ничего толкового не нашел.

Re: класс полином

Добавлено: 03 ноя 2009, 16:13
Romeo
Мой вариант правильней, чем твой, как мне кажется. Можешь дать пример, когда мой вариант оператора += работает неправильно? Если дашь, то я исправлю.

По поводу Clear. Cделай сам метод Clear. Вынеси в него то, что сейчас у тебя в деструкторе. В деструкторе оставь вызов Clear.

Re: класс полином

Добавлено: 03 ноя 2009, 21:19
inlaf

Код: Выделить всё

class Polynom 
{
private:
	size_t m_Dim;	//размер
	double *m_Pol; 
public:
//....

~Polynom();		
void Clear();
};
//.....
 void Polynom:: Clear()
{
	delete[] m_Pol;
}

Polynom::~Polynom() 
{	
        cout << szbuf.toOem("Полином успешно удалён ...") << endl;
	void Clear();
	//delete[] m_Pol;
}

имея.

Код: Выделить всё


//....

main()

// ....
    cout <<szbuf.toOem("Использование бинарного оператора +=:");
    double mass3[]={1,1,1}; // x^2 + x + 1
    Polynom p6(2,mass3);
    double mass4[]={4,3,100,100,30}; // 4x^4 + 3x^3 + 100x^2 + 100x + 30
    Polynom p7(4,mass4);
    p6+=p7;
    p6.Show();

после перегрузки на выходе имеем.
5*x^4+4*x^3+101*x^2+100*x^1+30

когда должно 4*x^4+3*x^3+101*x^2+101*x^1+31

я себе так это представляю.

у меня конструктор Show выводит полином со старшей степени по убыванию.

еще можешь дать пару советов по оператору *= ?

Re: класс полином

Добавлено: 04 ноя 2009, 01:38
Romeo
Задавая полином, ты определяешь в конструкторе его коэффициенты, начиная с младшей степени, а не начиная со старшей (по крайней мере такой вывод я сделал, изучив твой оператор +=).

Таким образом, ты имеешь следующее:

Код: Выделить всё

   double mass3[]={1,1,1}; // 1 + x + x^2
   Polynom p6(2,mass3);
   double mass4[]={4,3,100,100,30}; // 4 + 3x + 100x^2 + 100x^3 + 30x^4
   Polynom p7(4,mass4);
   p6+=p7;
   p6.Show(); // 5 + 4*x + 101*x^2 + 100*x^3 + 30x^4
Так что всё честно работает.

По поводу оператора *=. Там всё сложнее, но у меня есть мысль, как всё реализовать. Попробуй следующие рассуждения и вытекающий из них алгоритм.

1. Результирующий полном будет иметь максимальную степень, равную сумме максимальных степеней перемножаемых полиномов.

2. Коэффициент при n-й степени можно получить, пробежавшись в цикле k от 0 до n. В цикле k-й коэффициент первого полинома и (n-k)-й коэффициент второго полинома должны быть перемножены. Все полученные произведения должны быть сложена и дадут искомый коэффициент.

Вот пример:

y1 = a0 + a1*x + a2*x^2
y2 = b0 + b1*x + b2*x^2

Максимальные степени обоих полиномов 2, значит результирующий полином будет иметь степень 2+2 = 4.

y1*y1 = c0 + c1*x + c2*x^2 + c3*x^3 + c4*x^4

Теперь ищем коэффициенты:

c0 = сумма от 0 до 0... короче здесь остаются только перемноженные коэффициенты при нулевых степенях = a0*b0
c1 = сумма от 0 до 1 произведения коэффициентов при степенях k и 1-k = a0*b1 + a1*b0
c2 = сумма от 0 до 2 произведения коэффициентов при степенях k и 2-k = a0*b2 + a1*b1 + a2*b0
c3 = a0*b3 + a1*b2 + a2*b1 + a3*b0 = так как a3 и b3 коэффициентов не бывает, то остаётся = a1*b2 + a2*b1
c4 = a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 = так как a3, b3, a4, b4 не бывает, то остаётся только = a2*b2

Re: класс полином

Добавлено: 04 ноя 2009, 03:47
inlaf
точно. упустил из виду.
спасибо.

есть ли разница каким способом задается полином?
какой проще?
можно ли обойтись без метода CLear?

на это похоже?)

Код: Выделить всё


 for(int i=0;i < m_Dim;i++)
   {
      for(int j=0;j < no.m_Dim;j++)
	  {
          new_Pol[i+j]+=m_Pol[i]*no.m_Pol[j];
      }

Re: класс полином

Добавлено: 04 ноя 2009, 22:55
Romeo
1. Без метода Clear можно обойтись, никто тебя не заставляет его делать, я лишь объяснил что строка Clear() обозначает в моём коде.

2. Совсем не похоже. Проверь, оно не работает.