Проблема с кодом для определяющей функции NxN (C ++) - PullRequest
0 голосов
/ 27 февраля 2019

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

В данный момент я работаю над функциями для определения определителя функций, один для 2x2, один для 3x3, который вызывает 2x2 (рекурсивная формула для определителей, я уверен, что вы знаете детали).

Затем третья функция принимает матрицу в качестве входных данных, первоначально проверяя, является ли она 2x2 или 3x3, если это так, отправляет ее в соответствующую ранее упомянутую функцию.Далее мы рекурсивно удаляем строки и столбцы, следуя формуле определителя, пока не получим значение для определителя.

Этот код работает с матрицами 4x4, однако любая матрица, большая чем эта, приводит к неправильному ответу.

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

Извинения, если мое форматирование не лучшее, застрявшее на старом ноутбуке в данный момент.

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

double MatrixDet2By2(vector<vector<double>> matrix);
double MatrixDet3By3(vector<vector<double>> matrix);
double MatrixDet(vector<vector<double>> matrix);
//vector<vector<double>> CalcMinorMatrix(vector<vector<double>> matrix);
//vector<vector<double>> CalcCofactorMatrix(vector<vector<double>> matrix);

int main(int argc, char** argv)
{

    vector<vector<double>> testMatrix = {{1,4},{7,9}};
    vector<vector<double>> testMatrix2 = { {5,3,7},{6,-1,0},{4,-11,-2} };
    vector<vector<double>> testMatrix3 = 
    {
        {5,3,7,6},
        {6,-1,0,4},
        {4,-11,-2,3},
        {1,3,7,9},
    };
    vector<vector<double>> testMatrix4 = 
    {
        {1,2,-1,6,1},
        {6,-1,0,4,3},
        {4,0,-2,3,2},
        {1,3,7,2,3},
        {-2,7,0,2,5},
    };

    //cout << MatrixDet2By2(testMatrix) << endl;
    cout << MatrixDet(testMatrix4) << endl;

    cout << endl;
    return 0;
}

double MatrixDet2By2(vector<vector<double>> matrix)
{
    return (matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]);
}

double MatrixDet3By3(vector<vector<double>> matrix)
{
    vector<vector<double>> subMatrix1 = {
        {matrix[1][1], matrix[1][2]},
        {matrix[2][1], matrix[2][2]}
    };

    vector<vector<double>> subMatrix2 = {
        {matrix[1][0], matrix[1][2]},
        {matrix[2][0], matrix[2][2]}
    };

    vector<vector<double>> subMatrix3 = {
        {matrix[1][0], matrix[1][1]},
        {matrix[2][0], matrix[2][1]}
    };

    return ((matrix[0][0] * MatrixDet2By2(subMatrix1)) - (matrix[0][1] * MatrixDet2By2(subMatrix2)) + (matrix[0][2] * MatrixDet2By2(subMatrix3)));
}
/*
vector<vector<double>> CalcMinorMatrix(vector<vector<double>> matrix)
{
    vector<vector<double>> subMatrix1 = {
        {matrix[1][1], matrix[1][2]},
        {matrix[2][1], matrix[2][2]}
    };

    vector<vector<double>> subMatrix2 = {
        {matrix[1][0], matrix[1][2]},
        {matrix[2][0], matrix[2][2]}
    };

    vector<vector<double>> subMatrix3 = {
        {matrix[1][0], matrix[1][1]},
        {matrix[2][0], matrix[2][1]}
    };

    vector<vector<double>> subMatrix4 = {
    {matrix[0][1], matrix[0][2]},
    {matrix[2][1], matrix[2][2]}
    };

    vector<vector<double>> subMatrix5 = {
        {matrix[0][0], matrix[0][2]},
        {matrix[2][0], matrix[2][2]}
    };

    vector<vector<double>> subMatrix6 = {
        {matrix[0][0], matrix[0][1]},
        {matrix[2][0], matrix[2][1]}
    };

    vector<vector<double>> subMatrix7 = {
        {matrix[0][1], matrix[0][2]},
        {matrix[1][1], matrix[1][2]}
    };

    vector<vector<double>> subMatrix8 = {
        {matrix[0][0], matrix[0][2]},
        {matrix[1][0], matrix[1][2]}
    };

    vector<vector<double>> subMatrix9 = {
        {matrix[0][0], matrix[0][1]},
        {matrix[1][0], matrix[1][1]}
    };

    vector<vector<double>> matrixOfMinors = {
        {MatrixDet2By2(subMatrix1), MatrixDet2By2(subMatrix2), MatrixDet2By2(subMatrix3)},
        {MatrixDet2By2(subMatrix4), MatrixDet2By2(subMatrix5), MatrixDet2By2(subMatrix6)},
        {MatrixDet2By2(subMatrix7), MatrixDet2By2(subMatrix8), MatrixDet2By2(subMatrix9)},
    };

    return matrixOfMinors;
}

vector<vector<double>> CalcCofactorMatrix(vector<vector<double>> matrix)
{



    return matrix;
}
*/
double MatrixDet(vector<vector<double>> matrix)
{
    vector<vector<double>> tempMatrix{};

    static double totalDeterminant = 0;

    if (matrix.size() != matrix[0].size())
    {
        cout << "\r\nPlease enter a valid square matrix" << endl;
    }

    else if (matrix.size() == 2)
    {
        return MatrixDet2By2(matrix);
    }

    else if (matrix.size() == 3)
    {
        return MatrixDet3By3(matrix);
    }


    else
    {
        size_t pos = 0;


        for (auto value : matrix[0])
        {
            tempMatrix = matrix;
            tempMatrix.erase(tempMatrix.begin());

            for (size_t i = 0; i < tempMatrix.size(); i++)
            {
                if (tempMatrix[i].size() > pos)
                {
                    tempMatrix[i].erase(tempMatrix[i].begin() + pos);
                }
            }

            cout << "\r\n---------" << endl;
            for (auto vec : tempMatrix)
            {
                for (auto val : vec)
                {
                    cout << val << " ";
                }
                cout << endl;
            }
            cout << "\r\n---------" << endl;

            //totalDeterminant += MatrixDet(tempMatrix);


            if ((pos + 1) % 2 == 0)
            {
                totalDeterminant += (-value * MatrixDet(tempMatrix));
            }

            else
            {
                totalDeterminant += (value * MatrixDet(tempMatrix));
            }

            pos++;
        }



    }
    return totalDeterminant;

}

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Поскольку вы определяете переменную totalDeterminant в MatrixDet с помощью ключевого слова static, в вашей программе всегда есть только одна переменная totalDeterminant.И инициализатор = 0 применяется только в первый раз, когда программа попадает туда.Таким образом, при вычислении определителя самой первой вспомогательной матрицы 4x4 все идет хорошо.Затем этот результат умножается на matrix[0][0] и добавляется к totalDeterminant.Вычисление для второй вспомогательной матрицы 4x4 начинается с этого странного значения (1+matrix[0][0])*detMinor1 и начинает добавляться к нему.

Фактически, если вы только что вызвали MatrixDet для двух матриц 4x4 в одной программе, второй вызоввернет сумму двух определителей.

Вам понадобится отдельная сумма для каждого вычисления основной матрицы и подматрицы (поскольку результат определителя подматрицы должен быть умножен на элемент перед добавлением к чему-либо еще).Так что totalDeterminant НЕ должно быть static.Когда я удаляю static из вашей программы, он дает правильный конечный результат MatrixDet(testMatrix4) == -856.

Обратите внимание, что, как только общий случай верен, вы можете удалить код для случая 3x3 и, возможно, даже 2x2,Не забудьте поддержать матрицу 1x1: det [[x]] = x.

0 голосов
/ 27 февраля 2019

Одна ошибка в следующих строках

for (size_t i = 0; i < tempMatrix.size(); i++)
{
    if (tempMatrix[i].size() > pos)
    {
        tempMatrix[i].erase(tempMatrix[i].begin() + pos);
    }
}

Проверка if (tempMatrix[i].size() > pos) не требуется.

Все, что вам нужно, чтобы получить подматрицу, это просто исключить pos -й столбец.Вам нужно использовать:

// Remove the "pos" column of tempMatrix.
for (size_t i = 0; i < tempMatrix.size(); i++)
{
   tempMatrix[i].erase(tempMatrix[i].begin() + pos);
}

Вторая ошибка - это использование static переменной для totalDeterminant, как было указано @ aschepler .Линия

static double totalDeterminant = 0;

должна быть просто

double totalDeterminant = 0;
...