NxN 行列式函数 (C++) 的代码问题
Issue with code for NxN determinant function (C++)
我正在尝试编写一个矩阵求逆计算器(一直在为我的 uni 数学模块做一些与矩阵有关的事情,所以我认为这是练习递归函数的好方法)。
目前我正在研究用于计算函数行列式的函数,一个用于 2x2,一个用于 3x3,它调用 2x2 一个(行列式的递归公式我相信你知道这个练习)。
然后第三个函数将矩阵作为输入,最初检查它是 2x2 还是 3x3,如果是,则将其发送到前面提到的适当函数。接下来,我们按照行列式公式递归地消除行和列,直到我们最终得到行列式的值。
此代码最多适用于 4x4 矩阵,但是任何大于此的矩阵都会导致错误答案。
我是大学的第一年,对编程还比较陌生,这是我第一次尝试递归函数,如有任何建议,我们将不胜感激。我的数学讲师建议也许可以改用 cramers 规则,但看看我是否能让这个方法起作用会很有趣。
抱歉,我的格式不是最好的,目前卡在旧笔记本电脑上。
#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;
}
以下几行有一个错误
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);
}
第二个错误是 totalDeterminant
使用了 static
变量,正如 指出的那样。该行
static double totalDeterminant = 0;
需要简单
double totalDeterminant = 0;
由于您使用关键字 static
在 MatrixDet
中定义了变量 totalDeterminant
,因此您的程序中永远只有一个 totalDeterminant
变量。 = 0
初始化程序只在程序第一次到达那里时应用。因此,在计算第一个 4x4 小矩阵的行列式时,一切顺利。然后将该结果乘以 matrix[0][0]
并添加到 totalDeterminant
。第二个 4x4 小矩阵的计算从那个奇怪的值 (1+matrix[0][0])*detMinor1
开始并开始添加到它。
事实上,如果您只是在同一个程序中对两个 4x4 矩阵调用 MatrixDet
,则第二次调用将 return 两个行列式的总和。
您需要为每个主矩阵和子矩阵计算单独求和(因为子矩阵行列式的结果需要乘以一个元素,然后才能添加到其他任何东西)。所以 totalDeterminant
不必是 static
。当我从你的程序中删除 static
时,它给出了 MatrixDet(testMatrix4) == -856
.
的正确最终结果
请注意,一旦一般情况正确,您就可以删除 3x3 甚至 2x2 情况的代码。不要忘记支持 1x1 矩阵:det [[x]] = x
.
我正在尝试编写一个矩阵求逆计算器(一直在为我的 uni 数学模块做一些与矩阵有关的事情,所以我认为这是练习递归函数的好方法)。
目前我正在研究用于计算函数行列式的函数,一个用于 2x2,一个用于 3x3,它调用 2x2 一个(行列式的递归公式我相信你知道这个练习)。
然后第三个函数将矩阵作为输入,最初检查它是 2x2 还是 3x3,如果是,则将其发送到前面提到的适当函数。接下来,我们按照行列式公式递归地消除行和列,直到我们最终得到行列式的值。
此代码最多适用于 4x4 矩阵,但是任何大于此的矩阵都会导致错误答案。
我是大学的第一年,对编程还比较陌生,这是我第一次尝试递归函数,如有任何建议,我们将不胜感激。我的数学讲师建议也许可以改用 cramers 规则,但看看我是否能让这个方法起作用会很有趣。
抱歉,我的格式不是最好的,目前卡在旧笔记本电脑上。
#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;
}
以下几行有一个错误
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);
}
第二个错误是 totalDeterminant
使用了 static
变量,正如
static double totalDeterminant = 0;
需要简单
double totalDeterminant = 0;
由于您使用关键字 static
在 MatrixDet
中定义了变量 totalDeterminant
,因此您的程序中永远只有一个 totalDeterminant
变量。 = 0
初始化程序只在程序第一次到达那里时应用。因此,在计算第一个 4x4 小矩阵的行列式时,一切顺利。然后将该结果乘以 matrix[0][0]
并添加到 totalDeterminant
。第二个 4x4 小矩阵的计算从那个奇怪的值 (1+matrix[0][0])*detMinor1
开始并开始添加到它。
事实上,如果您只是在同一个程序中对两个 4x4 矩阵调用 MatrixDet
,则第二次调用将 return 两个行列式的总和。
您需要为每个主矩阵和子矩阵计算单独求和(因为子矩阵行列式的结果需要乘以一个元素,然后才能添加到其他任何东西)。所以 totalDeterminant
不必是 static
。当我从你的程序中删除 static
时,它给出了 MatrixDet(testMatrix4) == -856
.
请注意,一旦一般情况正确,您就可以删除 3x3 甚至 2x2 情况的代码。不要忘记支持 1x1 矩阵:det [[x]] = x
.