Автор: Пользователь скрыл имя, 15 Декабря 2012 в 20:14, практическая работа
Постановка задачи
Разработать стандартную процедуру вычисления обратной матрицы методом Жордана-Гаусса.
Описание метода
Сначала, нужно убедиться, что у матрицы есть обратная. Для этого нужно убедиться, что её определитель не равен нулю. Затем, к исходной матрице справа дописать единичную матрицу, такого же размера, как исходная.
Постановка задачи 3
Описание метода 3
Код 3
Заключение 8
|
Отчет о практической работе |
Вычисление обратной матрицы методом Жордана-Гаусса |
|
|
2012 год |
Постановка задачи 3
Описание метода 3
Код 3
Заключение 8
Разработать стандартную процедуру вычисления обратной матрицы методом Жордана-Гаусса.
Сначала, нужно убедиться, что у матрицы есть обратная. Для этого нужно убедиться, что её определитель не равен нулю. Затем, к исходной матрице справа дописать единичную матрицу, такого же размера, как исходная. Путём элементарных преобразований новую матрицу преобразовать так, что бы в левой части, на месте исходной, получилась единичная. Тогда справа будет обратная к исходной. Правильность обратной матрицы можно проверить, умножив исходную матрицу на полученную обратную. Если обратная найдена правильно, то результатом умножения будет единичная.
Файл Program.cs:
using System;
namespace Gauss
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Нахождение обратной матрицы методом Гаусса.\nС проверкой");
Console.WriteLine("Введите размерность матрицы");
int nMatrixSize = Convert.ToInt32(Console.
Matrix matrix = new Matrix(nMatrixSize, nMatrixSize);
for (int i = 1; i <= nMatrixSize; i++)
{
Console.WriteLine("Ввод {0} строки",i);
String line = Console.ReadLine();
String[] items = line.Split(" ".ToCharArray());
for (int j = 0; j < nMatrixSize; j++)
matrix[i, j + 1] = Convert.ToDouble(items[j]);
}
Console.WriteLine("Показать ход решения? [Д/Н]");
bool bShow = Console.ReadLine().ToLower() == "д";
Matrix m2 = matrix.Inverse(bShow);
Console.WriteLine("Результат:"
m2.Out();
Console.WriteLine("-----------
Console.WriteLine("
Matrix m3 = matrix * m2;
m3.Out();
Console.ReadKey();
}
}
}
Файл Matrix.cs:
using System;
/// <summary>
/// Класс, представляющий матрицу.
/// Элементы с [1,1] до [m,n] !
/// </summary>
public class Matrix
{
private double[,] matrix;
/// <summary>
/// Количество строк.
/// </summary>
private int amountOfRows;
/// <summary>
/// Количество столбцов.
/// </summary>
private int amountOfColumns;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="rows"> Количество строк. </param>
/// <param name="columns"> Количество столбцов. </param>
public Matrix(int rows, int columns)
{
matrix = new double[rows, columns];
amountOfRows = rows;
amountOfColumns = columns;
}
/// <summary>
/// Конструктор копирования.
/// </summary>
public Matrix(Matrix m)
{
amountOfRows = m.AmountOfRows;
amountOfColumns = m.AmountOfColumns;
matrix = new double[amountOfRows, amountOfColumns];
for (int i = 1; i <= amountOfRows; i++)
for (int j = 1; j <= amountOfColumns; j++)
this[i, j] = m[i, j];
}
/// <summary>
/// Индексатор для получения и установки элемента матрицы.
/// Диапазон индексов от [1,1] до [m,n].
/// </summary>
/// <param name="rowIndex"> Строка, в которой находится элемент. </param>
/// <param name="columnIndex"> Столбец, в котором находится элемент. </param>
public double this[int rowIndex, int columnIndex]
{
get
{
if (rowIndex > 0 && rowIndex <= amountOfRows && columnIndex > 0 &&
columnIndex <= amountOfColumns)
return matrix[rowIndex - 1, columnIndex - 1];
else
return 0.0;
}
set
{
if (rowIndex > 0 && rowIndex <= amountOfRows && columnIndex > 0 &&
columnIndex <= amountOfColumns)
matrix[rowIndex - 1, columnIndex - 1] = value;
}
}
/// <summary>
/// Свойство для чтения количества строк.
/// </summary>
public int AmountOfRows
{
get
{
return amountOfRows;
}
}
/// <summary>
/// Свойство для чтения количества столбцов.
/// </summary>
public int AmountOfColumns
{
get
{
return amountOfColumns;
}
}
/// <summary>
/// Объединяет две матрицы в одну путем присоединения столбцов.
/// </summary>
public Matrix Extend(Matrix m)
{
if (this.AmountOfRows == m.AmountOfRows)
{
Matrix res = new Matrix(this.AmountOfRows, this.AmountOfColumns + m.AmountOfColumns); //создать матрицу увеличенного размера
for (int i = 1; i <= res.AmountOfRows; i++) // работать по строкам
{
for (int j = 1; j <= this.AmountOfColumns; j++) // записать первые AmountOfColums элементов
res[i, j] = this[i, j];
for (int j = 1; j <= m.AmountOfColumns; j++) //начать писать со следующего элемента
res[i, this.AmountOfColumns + j] = m[i, j];
}
return res;
}
else
{
Console.WriteLine("Количество строк для расширения матрицы должны совпадать");
return null;
}
}
/// <summary>
/// Получает из одной матрицы другую между заданными номерами строк и столбцов.
/// (!) Крайние номера включаются.
/// </summary>
public Matrix Divide(int topRow, int bottomRow, int leftColumn, int rightColumn)
{
if (topRow >= 1 && bottomRow <= this.AmountOfRows && leftColumn >= 1 &&
rightColumn <= this.AmountOfColumns)
{
if (topRow <= bottomRow && leftColumn <= rightColumn)
{
//Создать итоговую урезанную матрицу
Matrix res = new Matrix(bottomRow - topRow + 1, rightColumn - leftColumn + 1);
for (int i = 1; i <= res.AmountOfRows; i++)
for (int j = 1; j <= res.AmountOfColumns; j++)
res[i, j] = this[i + topRow - 1, j + leftColumn - 1];
return res;
}
else
{
Console.WriteLine("
return null;
}
}
else
{
Console.WriteLine("Выход за границу матрицы");
return null;
}
}
/// <summary>
/// Перегруженный оператор (*) для умножения двух матриц.
/// </summary>
public static Matrix operator *(Matrix m1, Matrix m2)
{
if (m1.AmountOfColumns == m2.AmountOfRows)
{
Matrix result = new Matrix(m1.AmountOfRows, m2.AmountOfColumns);
for (int i = 1; i <= result.AmountOfRows; i++)
for (int j = 1; j <= result.AmountOfColumns; j++)
{
double elem = 0;
for (int k = 1; k <= m1.AmountOfColumns; k++)
elem += m1[i, k] * m2[k, j];
result[i, j] = elem;
}
return result;
}
else
{
Console.WriteLine("Матрицы не согласованы!");
return null;
}
}
/// <summary>
/// Перегруженный оператор (+) для сложения матрицы и числа.
/// </summary>
public static Matrix operator +(Matrix m, double number)
{
Matrix result = new Matrix(m);
for (int i = 1; i <= result.AmountOfRows; i++)
result[i, i] += number;
return result;
}
/// <summary>
/// Возвращает обратную матрицу.
/// </summary>
public Matrix Inverse(bool bShowP)
{
if (this.Det() == 0)
{
throw new System.Exception("Определитель матрицы равен нулю!");
}
Matrix a = new Matrix(this);
Matrix E = new Matrix(this.AmountOfRows, this.AmountOfRows) + 1;
a = a.Extend(E);
if (bShowP)
{
a.Out();
Console.WriteLine("===========
}
for (int k = 1; k <= a.AmountOfRows; k++)
{
if (a[k, k] == 0) //Если ноль (должно быть не ноль)
for (int i = k + 1; i <= a.AmountOfRows; i++)
if (a[k, i] != 0) //найти первый не ноль
{
a.SwapRows(i, k); //обменять
break;
}
double delElem = a[k, k]; //элемент, на который делить
a.MulRow(k, 1 / delElem); //делить всю строку (получаем 1 на элементе диагонали)
for (int i = k + 1; i <= a.AmountOfRows; i++) //Нули под всей диагональю в этом столбце
a.SumRows(k, i, -a[i, k]); //Суммирование всех строк, с указанной и умноженной
if (bShowP)
{
a.Out();
Console.WriteLine("===========
}
}
a.MulRow(a.AmountOfRows, 1 / a[a.AmountOfRows, a.AmountOfRows]); //сделать единицу на самом правом-нижнем элементе
for (int i = a.AmountOfRows; i > 1; i--) //Обработать элементы над диагональю
for (int k = i - 1; k >= 1; k--)
a.SumRows(i, k, -a[k, i]);
//убрать получившуюся слева единичную матрицу и вернуть остаток
return a.Divide(1, a.AmountOfRows, a.AmountOfRows + 1, a.AmountOfColumns);
}
/// <summary>
/// Прибавляет к строке rowDestination строку rowSource, умноженную на элемент number.
/// </summary>
public void SumRows(int rowSource, int rowDestination, double number)
{
if (rowSource != rowDestination)
for (int i = 1; i <= this.AmountOfColumns; i++)
this[rowDestination, i] += this[rowSource, i] * number;
else
Console.WriteLine("Строки не должны совпадать");
}
/// <summary>
/// Меняет местами строки.
/// </summary>
public void SwapRows(int row1, int row2)
{
if (row1 == row2)
return; //нечего менять
else
{
for (int i = 1; i <= this.AmountOfColumns; i++)
{
double temp = this[row1, i];
this[row1, i] = this[row2, i];
this[row2, i] = temp;
}
}
}
/// <summary>
/// Умножает строку на число.
/// </summary>
public void MulRow(int row, double number)
{
for (int i = 1; i <= this.AmountOfColumns; i++)
this[row, i] *= number;
}
/// <summary>
/// Выводит матрицу на экран.
/// </summary>
public void Out()
{
for (int i = 1; i <= this.AmountOfRows; i++)
{
for (int j = 1; j <= this.AmountOfColumns; j++)
Console.Write("{0, 8:F5}", this[i, j]);
Console.WriteLine();
}
}
public double Det()
{
if (this.AmountOfRows != this.AmountOfColumns)
throw new Exception("Матрица должна быть квадратная");
Matrix temp = new Matrix(this);
double result = 1;
for (int k = 1; k <= temp.AmountOfRows - 1; k++)
{
double max = Math.Abs(temp[k, k]);
int row = k;
for (int i = k + 1; i <= temp.AmountOfRows; i++)
if (max < Math.Abs(temp[i, k]))
{
max = Math.Abs(temp[i, k]);
row = i;
}
if (max == 0)
return 0;
if (row != k)
{
temp.SwapRows(row, k);
result = -result;
}
for (int i = k + 1; i <= temp.AmountOfRows; i++)
temp.SumRows(k, i, -temp[i, k] / temp[k, k]);
}
for (int i = 1; i <= temp.AmountOfRows; i++)
result *= temp[i, i];
return result;
}
}
В процессе работы
был разработан класс матрицы
и испытаны его функции. Вычисления
имеют высокий уровень
Информация о работе Вычисление обратной матрицы методом Жордана-Гаусса