我要在这里完成的是一些NxN矩阵的行列式的计算。行列式的定义如下:det M = MC(M)
,其中i从1到N循环,k是任意选择的常数,使得1
“ C”是定义如下的辅因子:C(M) = (-1) det M
,其中M {i,j}表示(N-1)x(N-1)矩阵,其条目由删除第i行第j列的M的原始条目组成
现在,这是我的代码:
template <typename T, const int N>
T determinant(const TMatrixNxM<T, N, N> &par_value)
{
T result = T(0);
switch (N)
{
case 1:
//Hardcoded for 1x1 matrix:
result = par_value[0][0];
break;
case 2:
//Hardcoded for 2x2 matrix:
result = par_value[0][0] * par_value[1][1] - par_value[0][1] * par_value[1][0];
break;
case 3:
//Hardcoded for 3x3 matrix:
result = par_value[0][0] * (par_value[1][1] * par_value[2][2] - par_value[1][2] * par_value[2][1]) - par_value[0][1] * (par_value[1][0] * par_value[2][2] - par_value[1][2] * par_value[2][0]) + par_value[0][2] * (par_value[1][0] * par_value[2][1] - par_value[1][1] * par_value[2][0]);
break;
default:
//i loops through 0 to N-1, k is arbitrarily chosen to be 0
for (int i = 0; i < N; i++)
{
result += par_value[i][0] * cofactor(par_value, i, 0);
}
break;
}
return result;
}
template <typename T, const int N>
T cofactor(const TMatrixNxM<T, N, N> &par_value, int par_i, int par_j)
{
T result = T(0);
//Construct the new matrix, without the i-th row j-th column
TMatrixNxM<T, N - 1, N - 1> newMatrix;
int k = 0;
for (int i = 0; i < N - 1; i++)
{
int l = 0;
if (k == par_i) k++;
for (int j = 0; j < N - 1; j++)
{
if (l == par_j) l++;
newMatrix[i][j] = par_value[k][l];
l++;
}
k++;
}
result = pow(-1, (par_i + 1) + (par_j + 1)) * determinant(newMatrix); //I have to add +1 to i and j since I started from 0
return result;
}
并对其进行测试:
TMatrixNxM<float, 3, 3> mat1;
//Set values
float det = determinant(mat1);
但是,编译器给我这些错误:
警告3警告C4200:使用了非标准扩展名:结构/联合中的零大小数组
错误4错误C2118:下标为负
指的是保存矩阵值的数据数组
当我看到编译器输出的其余部分时,我看到它正在尝试推导N设置为0甚至-1的参数。这里发生了什么?显然,它永远都不会走那么远(实际上,正如我所看到的,它不应该低于3)。
另外,如果我注释掉辅助因子函数中对行列式函数的递归调用,它将进行编译(它也可以正确计算新矩阵)。或者,如果我注释掉行列式函数中的整个“默认”部分,它将进行编译(并且它也可以正确计算硬编码的行列式)。
感谢您的时间
编辑1
在注释中请求的代码,显示数据数组的声明:
template <typename T, const int N, const int M>
class TMatrixNxM
{
public:
TMatrixNxM(T = T(0));
//Other things
protected:
TVectorND<T, M> data[N];
};
和
template <typename T, const int N>
class TVectorND
{
public:
TVectorND(T = T(0));
//Other things
protected:
T data[N];
};
最佳答案
即使未实际到达代码,编译器也需要能够编译determinant
的整个主体。因此,即使对于N = 3
,您仍然需要能够使用cofactor
调用N = 3
,而后者又会使用determinant
调用N = 2
。反过来,这要求能够使用cofactor
调用N = 2
并使用determinant
调用N = 1
,依此类推,直到获得N = -1
和编译错误为止。
代替在switch
中的N
上使用determinant
,而使用重载模板:
template <typename T>
T determinant(const TMatrixNxM<T, 1, 1> &par_value)
{
T result = T(0);
result = par_value[0][0];
return result;
}
template <typename T>
T determinant(const TMatrixNxM<T, 2, 2> &par_value)
{
T result = T(0);
result = par_value[0][0] * par_value[1][1] - par_value[0][1] * par_value[1][0];
return result;
}
template <typename T>
T determinant(const TMatrixNxM<T, 3, 3> &par_value)
{
T result = T(0);
result = par_value[0][0] * (par_value[1][1] * par_value[2][2] - par_value[1][2] * par_value[2][1]) - par_value[0][1] * (par_value[1][0] * par_value[2][2] - par_value[1][2] * par_value[2][0]) + par_value[0][2] * (par_value[1][0] * par_value[2][1] - par_value[1][1] * par_value[2][0]);
return result;
}
template <typename T, const int N>
T determinant(const TMatrixNxM<T, N, N> &par_value)
{
static_assert(N >= 4, "Default determinant called for N<4");
T result = T(0);
//i loops through 0 to N-1, k is arbitrarily chosen to be 0
for (int i = 0; i < N; i++)
{
result += par_value[i][0] * cofactor(par_value, i, 0);
}
return result;
}
Demo。
关于c++ - 模板参数推导出错,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24987240/