Вычисление обратной матрицы методом Жордана-Гаусса

Автор: Пользователь скрыл имя, 15 Декабря 2012 в 20:14, практическая работа

Краткое описание

Постановка задачи
Разработать стандартную процедуру вычисления обратной матрицы методом Жордана-Гаусса.
Описание метода
Сначала, нужно убедиться, что у матрицы есть обратная. Для этого нужно убедиться, что её определитель не равен нулю. Затем, к исходной матрице справа дописать единичную матрицу, такого же размера, как исходная.

Оглавление

Постановка задачи 3
Описание метода 3
Код 3
Заключение 8

Файлы: 1 файл

Отчет о практической работе — копия.docx

— 68.69 Кб (Скачать)

 

 

 

 

Отчет о практической работе

Вычисление обратной матрицы  методом Жордана-Гаусса

 

    

 

    

 

 

 

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.ReadLine());

            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;

               

    }  

 

}

Заключение

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

Результаты работы

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

  1. Конспект  лекций по алгебре

 

 

 


Информация о работе Вычисление обратной матрицы методом Жордана-Гаусса