Программа для вычислений над матрицами

Тип работы:
Курсовая
Предмет:
Программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

Содержание

Введение

1. Матрицы

1.1 Основные действия над матрицами

2. Вектор

2.1 Умножение вектора на матрицу

3. Классы

3.1 Конструкторы и деструкторы

3.2 Перегрузка операций

3.3 Дружественные функции

3.4 Неявный указатель this

3.5 Код программы

3.6 Результаты

3.7 Проверка результатов в Mathcad

Список литературы

Введение

На сегодняшний день математическое программирование — важная составляющая всего программирования. Большие и сложные вычисления благодаря простым программам становятся простыми.

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

В качестве среды программирования выбрана MS Visual Studio 2008 и язык программирования C++.

1. Матрицы

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

расположенных в m строках и n столбцах. Матрица называется квадратной, если.

1.1 Основные действия над матрицами

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

Суммой матриц является матрица, элементами которой являются соответственно сумма элементов исходных матриц.

Операция умножения матрицы любого размера на произвольное число сводится к умножению каждого элемента матрицы на это число.

Транспонирование матрицы — операция, при которой матрица отражается относительно главной диагонали, то есть

Если A — матрица размера, то AT — матрица размера.

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

В первом множителе должно быть столько же столбцов, сколько строк во втором. Если матрица A имеет размерность, B —, то размерность их произведения AB = C есть.

2. Вектор

Если матрица состоит только из одного столбца или строки, то такой объект называется вектором. Размерностью вектора называется число его элементов.

2.1 Умножение вектора на матрицу

Если имеется некоторая матрица, А размерностью и некоторый вектор B размерностью n, то при умножении получаем вектор С размерностью m.

В результате умножения матрицы на вектор будем иметь матрицу-столбец, у которой количество строк равно количеству строк исходной матрицы.

В результате умножения вектора на матрицу будем иметь матрицу-строку, у которой количество столбцов равно количеству столбцов исходной матрицы.

3. Классы

Класс — это тип структуры, позволяющий включать в описание типа не только элементы данных, но и функции (функции-элементы или методы).

Для ограничения доступа к элементам класса используются следующие спецификаторы доступа:

public- ограничений доступа нет;

protected- доступны только в порожденных классах;

private- доступны только в своем классе.

3.1 Конструкторы и деструкторы

Добавим в класс функцию

Matrix (int m, int n)

Такая функция называется конструктором и служит для инициализации создаваемого объекта данных. Имя конструктора должно совпадать с именем класса, конструктор н должен возвращать значений и содержать оператор return. Тип его явно не описывается. Конструктор может быть перегружен, поэтому у любого нового типа данных могут быть несколько конструкторов.

~Matrix () — специальный оператор, который называется деструктором. Он необходим для того, чтобы корректно завершить существование нашего объекта, то есть освободить память в куче.

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

Matrix (const Matrix & A) называется конструктором копий. Он используется при создании объекта с инициализацией его объектом того же типа.

Кроме того, конструктор копии используется при инициализации формального параметра функции в случае передачи ей объекта по значению, и при возврате объекта из функции по оператору return. При передаче ссылок и указателей конструктор копии не используется.

Неявный конструктор копии обеспечивает простое поэлементное копирование одного объекта во второй. Такой вид копирования часто называют поверхностным.

3.2 Перегрузка операций

Большинство операций языка С++ для новых типов данных может быть перегружено. Для перегрузки операции необходимо создать функцию с названием, состоящим из ключевого слова operator и знака перегружаемой операции. Количество параметров этой функции определяется тем, одноместная или двухместная операция перегружается, а также наличием неявных элементов у методов класса.

Перегрузка операций предполагает введение в язык двух взаимосвязанных особенностей: возможности объявлять в одной области видимости несколько процедур или функций с одинаковыми именами и возможности описывать собственные реализации операций.

Например, чтобы перегрузить оператор сложения, нужно определить функцию с именем operator+.

Операторные функции перегруженных операторов, за исключением new и delete, должны подчиняться следующим правилам:

— операторная функция должна быть либо нестатической фенкцией-членом класса, либо принимать аргумент типа класса или перечислимого типа, или аргумент, который является ссылкой на тип класса или перечислимый тип;

— операторная функция не может изменять число аргументов или приоритеты операторов и порядок их выполнения по сравнению с использованием соответствующео оператора для встроенных типов данных;

— операторная функция унарного оператора, объявленная как функция-член, не должна иметь параметров; если же она объявлена как глобальная функция, она должна иметь один параметр;

— операторная функция не может иметь параметры по умолчанию и др.

3.3 Дружественные функции

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

В языке С++ реализована возможность обойти данное ограничение с помощью друзей. С++ позволяет объявить 2 вида друзей класса: дружественную функцию или дружественный класс.

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

Чтобы объявить функцию дружественной некоторому классу, в определение этого класса включают ее прототип, перед которым ставится ключевое слово friend.

friend ostream& operator< <(ostream& os, const Matrix& A)

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

Функция может быть дружественна сразу нескольким классам.

3.4 Неявный указатель this

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

имя_типа *this;

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

Использовать указатель this для доступа к элементам класса можно, но вряд ли целесообразно, поскольку это и так подразумевается по умолчанию. Явно использовать this необходимо только в тех случаях, когда требуется работа непосредственно с адресами объектов, например, при организации динамических структур данных.

Создадим программу, которая будет реализовывать работу с классом Matrix.

3.5 Код программы

#include «stdafx. h»

#include < iostream>

#include «conio. h»

#include «math. h»

#include «time. h»

using namespace std;

// КЛАСС MATRIX

class Matrix

{

public:

double** M;

int m; // число строк

int n; // число столбцов

public:

// конструктор по умолчанию

Matrix ();

// конструктор

Matrix (int m, int n);

// конструктор копий

Matrix (const Matrix & A);

// заполнение матрицы случайными числами

void SetMatrix ();

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

Matrix& operator=(Matrix & A);

// перегрузка оператора сложения

Matrix operator+(Matrix &);

// перегрузка оператора умножения на число

Matrix operator*(const int &);

// умножение матрицы на матрицу

Matrix operator*(Matrix &);

// транспонирование матрицы

Matrix& operator^(const Matrix &);

// перегрузка оператора вывода в поток

friend ostream& operator< <(ostream& os, const Matrix& A);

// деструктор

~Matrix ();

};

// КЛАСС VECTOR

class Vector

{

double *v;

int n;

public:

// конструктор

Vector (int n);

// конструктор копий

Vector (const Vector & a);

// деструктор

~Vector ();

// заполнение вектора случайными числами

void SetVector ();

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

Vector& operator=(Vector & a);

// перегрузка оператора вывода в поток

friend ostream& operator< <(ostream& os, const Vector& a);

// умножение вектора на матрицу

Vector operator*(const Matrix & A);

};

// Конструктор по умолчанию

Matrix: :Matrix ()

{

M = NULL;

}

// Конструктор

Matrix: :Matrix (int _m, int _n)

{

m = _m;

n = _n;

M = new double*[m];

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

M[i] = new double[n];

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

for (int j = 0; j < n; j++)

{

M[i][j] = 0;

}

}

// Конструктор копий

Matrix: :Matrix (const Matrix & A)

{

m = A. m;

n = A. n;

M = new double*[m];

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

M[i] = new double[n];

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

for (int j = 0; j < n; j++)

{

M[i][j]=A. M[i][j];

}

}

// Заполнение матрицы случайными числами

void Matrix: :SetMatrix ()

{

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

{

for (int j = 0; j < n; j++)

{

M[i][j]=(double)((rand ()%200)-100. 0);

}

}

}

// Перегрузка оператора присваивания

Matrix& Matrix: :operator =(Matrix & A)

{

if (M≠NULL)

{

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

{

delete[] M[i];

}

delete[] M;

}

M = new double*[m];

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

M[i] = new double[n];

m = A. m;

n = A. n;

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

for (int j = 0; j < n; j++)

M[i][j] = A. M[i][j];

return *this;

}

// Сложение матриц

Matrix Matrix: :operator+(Matrix & A)

{

Matrix temp (m, n);

if (n≠A.n || m≠A. m)

{

cout< <"Сложение матриц невозможно. n"

«Не совпадают размерности! n»

«Программа завершила работу. n»;

exit (0);

}

else

{

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

for (int j = 0; j < n; j++)

temp. M[i][j] = M[i][j] + A. M[i][j];

return temp;

}

}

// Умножение матрицы на число

Matrix Matrix: :operator*(const int & k)

{

Matrix temp (m, n);

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

for (int j = 0; j < n; j++)

temp. M[i][j] = M[i][j]*k;

return temp;

}

// Умножение матрицы на матрицу

Matrix Matrix: :operator*(Matrix & A)

{

Matrix temp (m, A. n);

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

{

for (int j = 0; j < n; j++)

temp. M[i][j] = 0;

}

if (n≠A. m)

{

cout< <"Умножение матриц невозможно. n"

«Не совпадают размерности! n»

«Программа завершила работу. n»;

exit (0);

}

else

{

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

for (int j = 0; j < n; j++)

for (int k = 0; k < A. n; k++)

temp. M[i][k] += M[i][j] * A. M[j][k];

}

return temp;

}

// Транспонирование матрицы

Matrix& Matrix: :operator ^(const Matrix & A)

{

m = A. m;

n = A. n;

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

for (int j = 0; j < n; j++)

{

M[i][j] = A. M[j][i];

}

return *this;

}

// Деструктор

Matrix: :~Matrix ()

{

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

{

delete[] M[i];

}

delete[] M;

}

// Операция вывода

ostream& operator< <(ostream& os, const Matrix& A)

{

os< <'n';

for (int i = 0; i < A. m; i++)

{

for (int j = 0; j < A. n; j++)

os< <A. M[i][j]<<"t";

os< <'n';

}

return os;

}

// Конструктор

Vector: :Vector (int _n)

{

n = _n;

v = new double[n];

}

// Конструктор копий

Vector: :Vector (const Vector & a)

{

n = a. n;

v = new double[n];

for (int i = 0; i < n; i++)

v[i] = a. v[i];

}

// Деструктор

Vector: :~Vector ()

{

delete[] v;

}

// Заполнение вектора случайными числами

void Vector: :SetVector ()

{

v = new double[n];

for (int i = 0; i < n; i++)

{

v[i]=(double)((rand ()%200)-100. 0);

}

}

// Перегрузка оператора присваивания

Vector& Vector: :operator =(Vector & a)

{

n = a. n;

for (int i = 0; i < n; i++)

v[i] = a. v[i];

return *this;

}

// Умножение вектора на матрицу

Vector Vector: :operator* (const Matrix & A)

{

Vector temp (A. n);

for (int i=0; i< A. n; i++)

temp. v[i]=0;

for (int i = 0; i < A. m; i++)

for (int j = 0; j < A. n; j++)

temp. v[j] += v[i]*A. M[i][j];

return temp;

}

// Операция вывода

ostream& operator< <(ostream& os, const Vector& a)

{

os< <'n';

for (int i = 0; i < a. n; i++)

{

os< <a. v[i]<<" «;

os< <' ';

}

os< <'n';

return os;

}

int _tmain (int argc, _TCHAR* argv[])

{

setlocale (LC_CTYPE, «Russian_Russia. 1251»);

srand ((unsigned)time (NULL));

Matrix A (3,3), B (3,3), C (3,3), D (3,3), E (3,3), F (3,3), G (4,2), I (2,6), H (4,6);

Vector v (3), s (3);

A. SetMatrix ();

B. SetMatrix ();

G. SetMatrix ();

I. SetMatrix ();

v. SetVector ();

cout< <endl<<"Матрица А: «<<endl;

cout< <A;

cout< <endl<<"Матрица B: «<<endl;

cout< <B;

C = A + B;

cout< <endl<<"Матрица C=A+B: «<<endl;

cout< <C;

D = C*3;

cout< <endl<<"Матрица D=C*3: «<<endl;

cout< <D;

E = A*B;

cout< <endl<<"Матрица E=A*B: «<<endl;

cout< <E;

F^A;

cout< <endl<<"Матрица F=At: «<<endl;

cout< <F;

cout< <endl<<"Матрица G: «<<endl;

cout< <G;

cout< <endl<<"Матрица I: «<<endl;

cout< <I;

H=G*I;

cout< <endl<<"Матрица H=G*I: «<<endl;

cout< <H;

cout< <endl<<"Вектор v: «<<endl;

cout< <v;

s=v*A;

cout< <endl<<"Вектор s=v*A: «<<endl;

cout< <s;

return 0;

}

3.6 Результаты

3.7 Проверка результатов в Mathcad

программа матрица класс вектор

Список литературы

Бьeрн Страуструп. Справочное руководство по C++, 1995

Глушаков С. В. Программирование на С++, изд. 2-е, доп. и переработ. — М. :АСТ, 2008. — 685 с.

Харви Дейтел, Пол Дейтел. Как программировать на С. -- Бином-Пресс, 2008. -- 1024 с.

www.

ПоказатьСвернуть
Заполнить форму текущей работой