русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Определение программного класса многомерных векторов


Дата добавления: 2015-01-16; просмотров: 976; Нарушение авторских прав


Итак, составим включаемый файл vector.h, который будет содержать все, о чем мы договорились в предыдущем теоретическом подразделе. Для этого вначале рассмотрим структуру класса для работы с векторами, алгоритмы для работы с объектами типа «вектор» и примеры методов векторного класса, реализующие эти алгоритмы:

template <class YourOwnFloatType> class vector

{

Класс для работы с векторными объектами – параметризованный, то есть мы определяем только шаблон, по которому для конкретных типов, подставляемых вместо YourOwnFloatType, компилятор автоматически генерирует класс.

long m;

Вектор будет характеризоваться размерностью (длиной), которая может быть любым натуральным числом. Скаляры можно рассматривать как вектора размерности 1, комплексные числа –как вектора размерности 2 и т.д. В общем случае размерность вектора равна числу его составляющих, т.е. размерность вектора (а1, а2, …, аn) – n.

YourOwnFloatType *vec;

Данные, характеризующие вектор, мы будем хранить по этому указателю. В данном случае это –компоненты, или, как их ещё называют, координаты вектора. Это название не случайно: геометрические вектора размерности 2 –направленные отрезки на плоскости –могут быть связаны в декартовой системе координат с арифметическими координатами своих концов, если считать их всегда исходящими из начала координат.

virtual void In(istream &);

virtual void Out(ostream &);

Виртуальные функции чтения из потока и записи в поток; их необходимо переопределить в производных классах для обеспечения возможности использования единых перегруженных операторов << и >>. Явно использовать их необходимости нет, потому они и перенесены в приватную часть.

public:

В этом разделе –общедоступные методы класса, которые можно использовать для манипуляций с векторными объектами.



vector(char *);

Конструктор класса «вектор», параметром которого является имя текстового файла. Предполагается, что первым числом в этом файле является размерность вектора, после которого следуют данные. Этот конструктор определяет, откуда мы можем взять данные о векторе –размерность и компоненты.

vector();

Это конструктор по умолчанию, создающий нулевой вектор единичной размерности. Необходим при динамическом создании массивов векторов. Геометрически такой вектор –это точка на числовой прямой в отметке «0»; такой подход связан с трудностью решения вопроса о размерности вектора по умолчанию и отнюдь не является единственно правильным. Основная причина появления этого конструктора здесь –это требование компилятора.

vector(long);

Параметром этого конструктора является размерность вектора; после создания компоненты вектора обнуляются. Если, к примеру, принимаемая размерность –5, то мы получим вектор вида (0, 0, 0, 0, 0).

vector(long, YourOwnFloatType *);

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

Пусть, к примеру, параметры этого конструктора –размерность 3 и некий массив с числами 1, 2, 3, 4, 5, 6, …. В этом случае данный конструктор создаст вектор (1, 2, 3).

vector(vector<YourOwnFloatType> &);

Конструктор копирования (инициатор копии), создающий новый вектор из уже имеющегося. Размерность нового вектора устанавливается в размерность старого, а данные переписываются без изменений. В результате его выполнения мы получаем вектор, идентичный копируемому, но находящийся в другом участке памяти.

~vector();

Деструктор. Освобождает динамически распределённую память из-под компонент вектора.

friend vector<YourOwnFloatType> operator+ (vector <YourOwnFloatType> &, vector<YourOwnFloatType> &);

Дружественная функция сложения двух векторов. Складывает вектора только совпадающих размеров, вектор-результат конструируется и возвращается. При этом вектора одинаковых размерностей складываются по закону:

.

friend vector<YourOwnFloatType> operator+= (vector <YourOwnFloatType> &, vector<YourOwnFloatType> &);

Перегруженная операция сокращённого сложения складывает первый вектор со вторым, модифицируя при этом первый вектор (записывая результат сложения в него) и возвращает результат для того, чтобы он мог участвовать в других операциях над векторами типа а+=у) и т.п.

friend vector<YourOwnFloatType> operator-(vector <YourOwnFloatType> &, vector<YourOwnFloatType> &);

Дружественная функция для вычитания векторов одинаковой размерности; вычитает первый вектор из второго, конструируя и возвращая результат как новый вектор. При этом вектора одинаковых размерностей вычитаются по закону:

.

friend vector<YourOwnFloatType> operator-=(vector <YourOwnFloatType> &, vector<YourOwnFloatType> &);

Сокращённое вычитание, работающее так же, как и сокращённое сложение: из первого вектора вычитается второй, результат снова записывается в первый вектор, а его копия возвращается.

friend YourOwnFloatType operator* (vector <YourOwnFloatType> &, vector<YourOwnFloatType> &);

Скалярное произведение двух векторов одинаковой размерности –число того же типа, что и компоненты исходных векторов. Его можно получить по следующему закону:

friend vector<YourOwnFloatType> operator* (YourOwnFloatType, vector<YourOwnFloatType> &);

Ещё одна дружественная функция, перегружающая операцию умножения в несколько ином контексте, а именно –как умножение скаляра на вектор. Результатом является вектор той же размерности, что и исходный. Произведением вектора а(а1, а2, …, аn) на число a будет вектор aа(1, 2, …, n), то есть вектор, каждая компонента которого умножена на это число.

friend vector<YourOwnFloatType> operator* (vector <YourOwnFloatType> &, YourOwnFloatType);

Умножение скаляра на вектор операция коммутативная, что не избавляет нас от необходимости снова перегрузить операцию умножения, с теми же аргументами, но в другом порядке. Действительно, от соотношения aа=(1, 2, …, n) мы легко можем перейти к соотношению (а1a, а2a, …, аna)=аa.

friend vector<YourOwnFloatType> operator*= (vector <YourOwnFloatType> &, YourOwnFloatType);

Сокращённое умножение вектора на число. Первый аргумент этой функции –вектор –после выполнения данной операции модифицируется, копия результата возвращается.

friend ostream & operator << (ostream &, vector <YourOwnFloatType> &);

Перегруженная операция вывода вектора в поток. При этом выводятся только компоненты вектора, разделяемые пробелами; размерность не указывается. Модифицированный поток возвращается.

friend istream & operator >> (istream &, vector <YourOwnFloatType> &);

Ввод вектора из потока осуществляется путём приёма из потока количества чисел, равного размерности вектора. Модифицированный поток ввода возвращается для участия в дальнейших операциях ввода из него.

vector<YourOwnFloatType> operator=(vector <YourOwnFloatType> &);

Присвоение –операция, которая не может быть перегружена с использованием механизма дружественных функций. Первым, неявным параметром этой функции является текущий объект (*this), вторым –объект, присваиваемый текущему. При этом, если размерности присваиваемого и текущего векторов совпадают, компоненты последнего просто переписываются. В противном же случае размерность текущего вектора устанавливается в размерность копируемого, а память под компоненты перераспределятся, и только тогда происходит перепись данных. Возвращаемым значением является сам текущий вектор.

vector<YourOwnFloatType> operator-();

Унарный минус. Эта операция создаёт вектор той же размерности, что и текущий, с компонентами, имеющими противоположный знак, то есть Вектор, противоположный вектору а с координатами (а1, а2, …, аn) –вектор (–а) с координатами (–а1, –а2, …, –аn).

vector<YourOwnFloatType> operator+();

Эта функция-член включена только для полноты набора. Не выполняя ничего полезного, она просто возвращает копию текущего вектора.

vector<YourOwnFloatType> operator~();

Метод, для данного ненулевого вектора конструирующий вектор, имеющий то же направление и единичную длину, т.е. выполнятся нормирование данного вектора по модулю. Так как компонентами вектора-результата фактически являются косинусы углов данного вектора к координатным осям (а также длины проекций, т.к. вектор-результат –единичный), то данную операцию называют ещё и определением направляющих косинусов.

Модуль вектора (а1, а2, …, аn) определим как корень квадратный из скалярного произведения этого вектора на себя: |(а1, а2, …, аn)|= , а операцию нормирования по модулю –как деление каждой составляющей вектора на его модуль, или же умножение ненулевого вектора на величину, обратную модулю:

.

YourOwnFloatType operator!();

Метод, для вектора любой размерности определяющий его модуль. При этом делается, заметим, далеко не всегда корректное допущение, что длина вектора выражается в единицах того же типа, что и компоненты вектора. Например, для целых векторов эта операция даст лишь приближённый результат, а для многомерных векторов (например, комплексных) данная операция имеет смысл нормы.

virtual long IsEqual(void *);

Эта виртуальная функция сравнивает текущий вектор с объектом, лежащим по адресу, передаваемому через обобщённый указатель. При этом делается неявное предположение о том, что указатель содержит адрес вектора, а не чего-либо более экзотического. Преобразуя получаемый указатель к указателю на вектор, эта функция пытается сравнить его с текущим. Заметим, что вектора будут считаться равными, если выполнятся два условия –одинаковая размерность и совпадающие компоненты:

friend long operator==(vector<YourOwnFloatType> &, vector<YourOwnFloatType> &);

Используя описанную выше функцию, вводим операторное сравнение двух векторов –проверка на равенство…

friend long operator!=(vector<YourOwnFloatType> &, vector<YourOwnFloatType> &);

…и проверка на неравенство.

YourOwnFloatType &operator[](long a);

Индексирование элементов вектора –это операция, которая возвращает ссылку на компоненту вектора с заданным номером. Если этот номер выходит за границы размерности вектора, после диагностики возвращается специальный код ошибки. Так как данная функция ссылочная, то её можно использовать в операторах присваивания как слева, так и справа –ведь модифицируя ссылочный объект, мы фактически воздействуем на то, что под ним скрывается, то есть на саму векторную компоненту. Заметим, что вектор размерности а можно индексировать от 0 до (а–1), а не от 1 до а (!).

long getm() { return m; }

Размерность вектора можно узнать, используя этот метод.

};

 

По приведенным описаниям можно составить, к примеру, такой интерфейс для данного класса:

 

#ifndef __VECTOR_H

#define __VECTOR_H

#ifndef __FSTREAM_H

#include <fstream.h>

#endif

#ifndef __IOMANIP_H

#include <iomanip.h>

#endif

#ifndef __STDLIB_H

#include <stdlib.h>

#endif

#ifndef __MATH_H

#include <math.h>

#endif

#ifndef __EXCEPT_H

#include <except.h>

#endif

#ifndef __CSTRING_H

#include <cstring.h>

#endif

 

/*параметризованный класс для работы с векторными объектами*/

 

template <class YourOwnFloatType>/* подставьте свой тип*/

class vector

{ //приватные данные

long m; //размерность (длина) вектора

YourOwnFloatType *vec; /*указатель на элементы вектора*/

/*виртуальные функции чтения из потока и записи в поток; их необходимо переопределить в производных классах для обеспечения возможности использования единых перегруженных операторов << и >> */

virtual void In(istream &);

virtual void Out(ostream &);

public://общедоступные данные и функции

/*загрузка вектора из файла: dimension data1 data2... */

vector(char *);

vector();/*создание пустого вектора единичной размерности */

vector(long);/*создание пустого вектора заданной размерности */

vector(long, YourOwnFloatType *); /*создание вектора заданной размерности, заполняемого данными из массива */

//конструктор копирования

vector(vector<YourOwnFloatType> &);

~vector();//деструктор

friend vector<YourOwnFloatType> operator+ (vector <YourOwnFloatType> &, vector<YourOwnFloatType> &); //сложение двух векторов

friend vector<YourOwnFloatType> operator+= (vector <YourOwnFloatType> &, vector <YourOwnFloatType> &);//сложение с присвоением

friend vector<YourOwnFloatType> operator-(vector <YourOwnFloatType> &, vector<YourOwnFloatType> &); //вычитание

friend vector<YourOwnFloatType> operator-= (vector <YourOwnFloatType> &, vector <YourOwnFloatType> &);//вычитание с присвоением

friend YourOwnFloatType operator* (vector <YourOwnFloatType> &, vector<YourOwnFloatType> &); //скалярное умножение

friend vector<YourOwnFloatType> operator* (YourOwnFloatType, vector<YourOwnFloatType> &); //умножение числа на вектор

friend vector<YourOwnFloatType> operator* (vector<YourOwnFloatType> &, YourOwnFloatType ); //умножение вектора на число

friend vector<YourOwnFloatType> operator*= (vector<YourOwnFloatType> &, YourOwnFloatType ); //умножение вектора на число с присвоением

friend ostream &operator<<(ostream &, vector <YourOwnFloatType> &);//вывод вектора в поток

friend istream &operator>>(istream &, vector <YourOwnFloatType> &);//ввод вектора из потока

vector<YourOwnFloatType> operator= (vector <YourOwnFloatType> &);//присвоение

vector<YourOwnFloatType> operator-();/*унарный минус*/

vector<YourOwnFloatType> operator+();/*унарный плюс*/

vector<YourOwnFloatType> operator~(); /*нормирование (определение направляющих косинусов) */

YourOwnFloatType operator!();//модуль вектора

virtual long IsEqual(void *);

/*эта виртуальная функция сравнивает текущий вектор с объектом, лежащим по адресу, передаваемому через обобщённый указатель*/

friend long operator==(vector<YourOwnFloatType> &, vector<YourOwnFloatType> &);/*проверка на равенство */

friend long operator!=(vector<YourOwnFloatType> &, vector<YourOwnFloatType> &);/*проверка на неравенство */

YourOwnFloatType &operator[](long a);

//индексирование элементов вектора

long getm() { return m; }//размерность вектора

};

 

/*Теперь реализация объявленных методов класса vector */

 

//индикатор ошибки - некая константа

const long double MAX_LONGDOUBLE=1.7976931348e308;

 

/*

Создавать вектор можно по-разному. Например, если он находится на внешнем устройстве в формате m d1 d2 ... dm, где m - размерность вектора, а di - его компоненты, то имеем следующий конструктор:

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType>::vector(char *f) /*имя файла */

{

long i;

 

ifstream fp=f;//пытаемся открыть файл

if(!fp)//если не удалось

throw xmsg("Не могу открыть файл "+string(f)+ "\n");

fp>>m;//вводим размерность

if(m<=0)//проверка на корректность

throw xmsg("Размерность вектора некорректна \n"); //диагностика

try

{

vec=new YourOwnFloatType[m];/*попытка выделения памяти*/

}

catch(xalloc)

{

throw xmsg("Не хватает памяти \n");

}

for(i=0;i<m&&fp>>vec[i];i++);/*считывание из файла */

}

 

 

/*

В случае, когда нам известна лишь размерность вектора, но неизвестны его составляющие, предполагаем, что данный вектор является нулевым:

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType>::vector(long a):m(a)

//размерность вектора

{

long i;

 

if(m<=0)//проверка размерности

throw xmsg("Размерность вектора некорректна \n");

//диагностика

try

{

vec=new YourOwnFloatType[m];/*попытка выделения памяти */

}

catch(xalloc)

{

throw xmsg("Не хватает памяти \n");

}

for(i=0;i<m;vec[i++]=0);/*обнуление компонент вектора */

}

 

 

/*

Наконец, нам могут быть известны как размерность, так и компоненты вектора:

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType>::vector(long a,

YourOwnFloatType *v):m(a)

/*этот конструктор принимает размер и указатель на данные */

{

long i;

 

if(m<=0)//проверка размерности

throw xmsg("Размерность вектора некорректна \n");

//диагностика

try

{

vec=new YourOwnFloatType[m];/*попытка выделения памяти */

}

catch(xalloc)

{

throw xmsg("Не хватает памяти \n");

}

for(i=0;i<m;i++)

vec[i]=v[i];/*копирование из внешнего массива в вектор*/

}

 

 

/*

Есть ещё один случай, когда мы ничего не можем сказать о размерности и компонентах вектора - при создании массива векторов, то есть матрицы, когда для оператора new требуется конструктор без параметров или когда размер вектора заранее неизвестен.

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType>::vector():m(1)

{

try

{

vec=new YourOwnFloatType[m];/*попытка выделения памяти */

}

catch(xalloc)

{

throw xmsg("Не хватает памяти \n");

}

*vec=0;//обнуляем единственный имеющийся элемент

}

 

 

/*

В реальных расчетах могут использоваться векторы больших размерностей, поэтому размещаются они в свободной памяти компьютера, а когда необходимость в них отпадает - уничтожаются.

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType>::~vector()

{

delete []vec;//уничтожение динамического массива

}

 

 

/*

Необходимость в индексации вектора возникает в двух случаях:

· при получении составляющей вектора по её номеру и

· при изменении не всего вектора, а только одной его составляющей.

При этом, конечно, следует учитывать возможность ошибочного задания номера составляющей: допустимый диапазон значений [0,m).

*/

template <class YourOwnFloatType>

YourOwnFloatType &

vector<YourOwnFloatType>::operator[](long a)

{

static YourOwnFloatType error=MAX_LONGDOUBLE;

if(a>=0&&a<m)//если всё ОК

return vec[a];

else//при выходе за пределы вектора ругаемся

{

cerr<<"Индекс "<<a<<" вне диапазона вектора\n";

return error;

}

}

 

 

/*

Создавая вектор, можно попутно инициализировать его данными из уже существующего:

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType>::vector( vector<YourOwnFloatType> &ex) : m(ex.m)

/*это конструктор копирования, принимающий ссылку на вектор */

{

try

{

vec=new YourOwnFloatType[m];/*попытка выделения памяти*/

}

catch(xalloc)

{

throw xmsg("Не хватает памяти \n");

}

for(long i=0;i<m;i++)

vec[i]=ex[i];

/*здесь при копировании ех используется уже индексация*/

}

 

 

/*

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

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType> operator+

(vector<YourOwnFloatType> &f, vector<YourOwnFloatType> &s)

{

if(f.m!=s.m)//проверка на равенство размерностей

throw xmsg("Слагаемые вектора имеют различные длины \n");

//диагностика

vector<YourOwnFloatType> temp(f.m);

//создаём временный вектор

/*здесь работают операции индексирования для всех трёх векторов*/

for(long i=0;i<f.m;i++)

temp[i]=f[i]+s[i];

return temp;//возвращаем результирующий вектор

}

 

 

//сокращённая операция "сложение с присвоением"

template <class YourOwnFloatType>

vector<YourOwnFloatType> operator+=

(vector<YourOwnFloatType> &f, vector<YourOwnFloatType> &s)

{

return f=f+s;

}

 

 

/*

Введём несколько вспомогательных унарных операций:

- "минус":

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType> vector<YourOwnFloatType>:: operator-()

{

vector<YourOwnFloatType> temp(m);

//создаём временный вектор

/*Если this - это указатель на текущий объект векторного класса, то *this - это сам текущий объект класса vector, то есть тот, с которым мы сейчас работаем. А к любому векторному объекту мы можем применить операцию индексирования */

for(long i=0;i<m;i++)

temp[i]=-(*this)[i];

//temp[i]=-vec[i];

//temp.vec[i]=-vec[i];

//temp.operator[](i)=-operator[](i); etc...

return temp;//возвращаем результирующий вектор

}

 

 

//унарный плюс

template <class YourOwnFloatType>

vector<YourOwnFloatType> vector<YourOwnFloatType>:: operator+()

{

return *this;//возвращаем самого себя

}

 

 

/*

Операция, которую алгебраической назвать нельзя - это, скорее, пример очень распространённого тернарного отношения "скалярное произведение двух векторов":

*/

template <class YourOwnFloatType>

YourOwnFloatType operator*(vector<YourOwnFloatType> &f, vector<YourOwnFloatType> &s)

{

if(f.m!=s.m)

throw xmsg("Умножение векторов с несовпадающими размерами невозможно \n");//диагностика

YourOwnFloatType temp=0;

for(long i=0;i<f.m;i++)

temp+=f[i]*s[i];

//суммируем произведения составляющих векторов

return temp;

}

 

 

/*

Модуль вектора как квадратный корень скалярного произведения вектора на самого себя:

*/

template <class YourOwnFloatType> inline YourOwnFloatType vector<YourOwnFloatType>:: operator!()

{

return sqrt((*this)*(*this));

}

 

 

/*

нормирование вектора по модулю

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType> vector<YourOwnFloatType>::operator~()

{

vector<YourOwnFloatType> temp(m);

/*скалярное произведение текущего объекта на самого себя*/

YourOwnFloatType modul=!(*this);

for(long i=0;i<m;i++)

temp[i]=(*this)[i]/modul;/* направляющие косинусы*/

return temp;

}

 

 

/*

умножение числа на вектор":

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType> operator*

(YourOwnFloatType ld, vector<YourOwnFloatType> &v)

{

vector<YourOwnFloatType> temp=v;

for(long i=0;i<v.getm();i++)

temp[i]=temp[i]*ld;/* скорее, это даже "удлинение" вектора */

return temp;

}

 

 

/*

умножение вектора на число:

*/

template <class YourOwnFloatType>

inline vector<YourOwnFloatType> operator*

(vector<YourOwnFloatType> &v, YourOwnFloatType ld)

{

return ld*v;/*очень просто - вызвали другую функцию */

}

 

 

//операция сокращённого умножения вектора на число

template <class YourOwnFloatType>

vector<YourOwnFloatType> operator*=

(vector<YourOwnFloatType> &v, YourOwnFloatType ld)

{

return v=v*ld;

}

 

 

/*

Имея определённые бинарную операцию сложения векторов и унарную получения вектора, противоположного к данному, можно на векторном языке, не обращаясь к компонентам векторов, определить операцию вычитания:

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType> operator-

(vector<YourOwnFloatType> &f, vector<YourOwnFloatType> &s)

{

return f+(-s);

//return operator+(f,-s);

//return operator+(f,s.operator-());

}

 

 

//операция сокращённого вычитания

template <class YourOwnFloatType>

vector<YourOwnFloatType> operator-=

(vector<YourOwnFloatType> &f, vector<YourOwnFloatType> &s)

{

return f=f-s;

}

 

 

/*

При переписывании одного вектора в другой возможны два случая:

1. если размерность обоих векторов совпадает, то просто заменяем составляющие первого вектора компонентами второго;

2. в противном случае безжалостно уничтожаем первый вектор и создаём снова, используя второй как строительный материал.

*/

template <class YourOwnFloatType>

vector<YourOwnFloatType> vector<YourOwnFloatType>:: operator=(vector<YourOwnFloatType> &x)

{

if(m!=x.m)//если размеры не совпадают

{

delete []vec;/*уничтожаем содержимое текущего вектора */

m=x.m;//устанавливаем новый размер

try

{

vec=new YourOwnFloatType[m];/*попытка выделения памяти */

}

catch(xalloc)

{

throw xmsg("Не хватает памяти \n");

}

}

for(long i=0;i<m;i++)

vec[i]=x[i];/*копируем данные из вектора х в текущий*/

/*присвоение - это бинарная операция, первым параметром которой является объект, которому присваивают, вторым - объект, который присваивают. При этом первый объект, в отличие от всех остальных бинарных операций, меняется, и он же возвращается в качестве результата (это бывает необходимым для операций вида a=b=c;)*/

return *this;

}

 

 

/*Эта функция сравнивает текущий вектор с вектором, лежащим по адресу х. Для каждого класса, производного от векторного, не имеет смысла переопределять операторные функции проверки на равенство и неравенство - достаточно переопределить эту виртуальную функцию*/

template <class YourOwnFloatType>

long vector<YourOwnFloatType>::IsEqual(void *x)

{

if(m!=((vector<YourOwnFloatType>*)x)->m)

//при несовпадении размерностей

return 0; //констатируем несовпадение векторов

for(long i=0;i<m;i++)

if((*this)[i]!=

(*(vector<YourOwnFloatType>*)x)[i])

return 0;//если хоть один элемент не совпал

return 1;

}

 

 

/*

Сравнение векторов является тернарным отношением, результатом которого является число нуль, если векторы не равны и единица в противном случае.

Два вектора будем считать равными, если они имеют одинаковые длины и их соответствующие составляющие совпадают:

*/

template <class YourOwnFloatType>

long operator==(vector<YourOwnFloatType> &f,

vector<YourOwnFloatType> &s)

{

return f.IsEqual(&s);

}

 

 

/*

Неравенство векторов определим через равенство и операцию отрицания:

*/

template <class YourOwnFloatType> inline long operator!=(vector<YourOwnFloatType> &f,

vector<YourOwnFloatType> &s)

{

return !(f==s);//логично

}

 

 

/*Мощный I/O-механизм С++ позволяет в естественной форме выводить (вводить) векторы на любое устройство отображения информации. Для универсализации считывания и записи вектора в поток снова прибегнем к механизму виртуальных функций. С этой целью, по аналогии с printOn, определим две функции - одну для ввода, другую - для вывода */

 

template <class YourOwnFloatType>

void vector<YourOwnFloatType>::In(istream &is)

{

for(long i=0;i<m;i++)

is>>(*this)[i];

}

 

template <class YourOwnFloatType>

void vector<YourOwnFloatType>::Out(ostream &os)

{

for(long i=0;i<m;i++)

{

os.precision(100);

os<<(*this)[i]<<" ";/*компоненты разделяем пробелами */

}

}

 

//вывод в поток

template <class YourOwnFloatType>

ostream &operator<<(ostream &os,

vector<YourOwnFloatType> &x)

{

x.Out(os);

return os;

}

 

/* - ввод из потока */

template <class YourOwnFloatType>

istream &operator>>(istream &is,

vector<YourOwnFloatType> &x)

{

x.In(is);

return is;/*принимаем и возвращаем ссылку на поток ввода */

}

 

#endif



<== предыдущая лекция | следующая лекция ==>
Основные понятия | Общие сведения


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.823 сек.