【发布时间】:2021-06-19 01:07:24
【问题描述】:
我在矩阵模板中实现矩阵的行列式时遇到问题。我试图通过计算减少的关联矩阵中主对角线的乘积来获得行列式。问题是它只适用于某些情况并且不可靠。这是行列式的代码
template <typename T>
T Matrix<T>::Det() const {
if (Rows != Cols) {
cout << "Matrix must be square" << endl;
}
Matrix<T> r = Reduced();
T Det = 1;
for (int i=0; i<Rows; i++) {
Det *= r.getValue(i, i);
}
return Det;
}
由于高斯消除有效,我为任何给定矩阵(符合要减少的标准)获得的减少矩阵很好,所以我认为不会有任何问题,但我无法看看我错过了什么。 欢迎任何建议!
编辑: 正如有人指出的那样,这是一个最小的可重现示例。 这将是模板
#ifndef MATRIX_H
#define MATRIX_H
#include <vector>
#include <iostream>
using namespace std;
template <typename T>
class Matrix {
private:
unsigned int Rows;
unsigned int Cols;
T *Mat;
public:
Matrix(unsigned int Dim);
Matrix(unsigned int Rows, unsigned int Cols);
Matrix(unsigned int Rows, unsigned int Cols, const std::vector<T>& Vec);
Matrix(unsigned int Dim, const std::vector<T>& Vec);
Matrix(const Matrix<T>& M);
~Matrix();
T& getValue(unsigned int Row, unsigned int Col) const;
T Det() const;
Matrix<T> Reduced() const;
};
template <typename T>
Matrix<T>::Matrix(unsigned int Rows, unsigned int Cols)
: Rows(Rows), Cols(Cols) {
if (Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = 0;
}
}
template <typename T>
Matrix<T>::Matrix(unsigned int Dim)
: Rows(Dim), Cols(Dim) {
if(Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = 0;
}
}
template <typename T>
Matrix<T>::Matrix(unsigned int Rows, unsigned int Cols, const std::vector<T>& Vec)
: Rows(Rows), Cols(Cols) {
if (Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
if (Vec.size() != Rows*Cols) {
cout << "Los tamaños de la matriz y el vector no son iguales" << endl;
}
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = Vec[i];
}
}
template <typename T>
Matrix<T>::Matrix(unsigned int Dim, const std::vector<T>& Vec)
: Rows(Dim), Cols(Dim) {
if (Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
if (Vec.size() != Rows*Cols) {
cout << "Número inválido de filas o columnas" << endl;
}
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = Vec[i];
}
}
template <typename T>
Matrix<T>::Matrix(const Matrix<T>& M)
: Rows(M.Rows), Cols(M.Cols), Mat(new T[Rows * Cols]) {
for (int i = 0; i < Rows * Cols; i++)
Mat[i] = M.Mat[i];
}
template <typename T>
Matrix<T>::~Matrix() {
delete[] Mat;
}
template <typename T>
T &Matrix<T>::getValue(unsigned int Row, unsigned int Col) const {
if (Row<0 || Row>=Rows || Col<0 || Col>=Cols) {
cout << "Índice incorrecto" << endl;
}
return Mat[Row*Cols + Col];
}
template <typename T>
Matrix<T> Matrix<T>::Reduced() const {
if (Rows != Cols) {
cout << "La matriz debe ser cuadrada para reducirse" << endl;
}
Matrix<T> Tri(*this);
int n = Rows;
int m = 0;
for (int k=0; k<n-1; k++) {
if (Tri.Mat[k*Cols + k] == 0)
cout << "La matriz es singular" << endl;
for (int i = k+1; i<n; i++) {
m = Tri.Mat[i*Cols + k]/Tri.Mat[k*Cols + k];
for (int j = k+1; j<n; j++) {
Tri.Mat[i*Cols + j] = Tri.Mat[i*Cols + j] - m*Tri.Mat[k*Cols + j];
}
Tri.Mat[i*Cols + k] = 0;
}
}
return Tri;
}
template <typename T>
T Matrix<T>::Det() const {
if (Rows != Cols) {
cout << "Matrix must be square" << endl;
}
Matrix<T> r = Reduced();
T Det = 1;
for (int i=0; i<Rows; i++) {
Det *= r.getValue(i, i);
}
return Det;
}
template <class T>
ostream & operator<<(ostream &os, const Matrix<T> &Shw) {
for (int i=0; i<Shw.getRows(); i++) {
os << "| ";
for (int j=0; j<Shw.getCols(); j++) {
os << Shw.getValue(i,j) << " ";
}
os << "|\n";
}
return os;
}
#endif
这是 main.cc 上的实现
#include "matrix.h"
int main() {
Matrix<double> M1(2, 2, {1, 3, 5, 7});
cout << M1.Det() << endl;
Matrix<double> M2(3, 3, {1, 3, 5, 7, 8, 9, 11, 2, 14});
cout << M2.Det() << endl;
return 0;
}
输出如下
-8 //This one is okay
-143 //This one is not
【问题讨论】:
-
例如,如果计算 2x2 方阵 {1,3,5,7} 的行列式,它会输出 -8。但是对于 3x3 矩阵 {1,3,5,7,8,9,11,2,14} 打印 -143 这显然是错误的,因为正确的输出是 -273。我没有收到任何错误消息。
-
Reduced()函数中,变量m的类型必须为T. /*int*/ T m = 0;
-
[[1 3 5][7 8 9][11 12 14]]的行列式是 -13 而不是 -273。 -
我指出的矩阵是 2 而不是 12。
-
除了
m的类型不正确,正如@ardget 提到的那样,还要养成使用std::size_t对数组的大小、计数和索引的习惯。
标签: c++ templates matrix linear-algebra