我知道有人问过这个问题,但是我还没有真正找到对我有意义的答案。
我正在编写一个函数来计算C ++中的行列式。为此,我需要传递一个矩阵。
我的代码如下:
#include <stdlib.h>
#include <stdio.h>
double determinant(int N, double M[N][N]);
int main(){
double myMatrix[3][3] = {{1,2,3}, {4,5,6}, {3,6,1}};
double okay = determinant(4, myMatrix);
printf("determinant = %f\n", okay);
}
double determinant(int N, double M[N][N]){
double det=0.0;
//if N=2 matrix, use the easy formula
if(N==2){
det = M[0][0]*M[1][1] - M[0][1]*M[1][0];
}
//otherwise, find minor matrices, multiply by top row
else {
double Mminor[N-1][N-1];
double sign = 1.0;
for(int i=0; i<N; i++){
//get the minor matrix
for(int a=1;a<N;a++){
int m=0;
for(int b=0;b<N;b++){
if(b!=i){
Mminor[a-1][m] = M[a][b];
m++;
}
}
}
//add top row element times determinant of its minor
det += sign*M[0][i]*determinant(N-1, Mminor);
//swap the sign
sign *= -1.0;
}
}
return det;
}
如果我将其编译为C并使用C99编译器,则它运行良好且没有问题,可以为几种不同的测试矩阵提供正确的值。
但是我不需要将其编译为C,而是需要将其编译为C ++。而且它不会编译为C ++。 GNU编译器给出以下错误:
determinant.c:25:24: error: no matching function for call to 'determinant'
det += sign*M[0][i]*determinant(N-1, Mminor);
^~~~~~~~~~~
determinant.c:5:8: note: candidate function not viable: no known conversion from 'double [N - 1][N - 1]' to
'double (*)[N]' for 2nd argument
double determinant(int N, double M[N][N]){
^
determinant.c:36:16: error: no matching function for call to 'determinant'
double okay = determinant(4, myMatrix);
^~~~~~~~~~~
determinant.c:5:8: note: candidate function not viable: no known conversion from 'double [4][4]' to 'double (*)[N]'
for 2nd argument
double determinant(int N, double M[N][N]){
我知道C和C ++对2D数组有很深的成见,不喜欢它们并且拒绝使用它们,但是我所读的一切都建议通过将大小N指定为应该起作用的参数来建议。确实如此。在C99中。但是不能使用g ++编译器(既不是C ++ 99也不是C ++ 11)。
我必须使用一些特定的编译器标志吗?还是其他方法可以做到这一点?
要明确:我需要矩阵的大小灵活,因为每次调用函数时矩阵的大小都会不同。
如果可能的话,我想避免使用1D数组制作2D数组。我知道如何使用1D阵列执行此操作,我只想以更自然,更优雅的方式执行此操作。
谢谢。
编辑:而且我知道您会建议我使用vector <>代替。使用vector <>并不是最佳选择,因为所有这些都应该进入一个更大的程序中,该程序在大约20,000行处仅使用数组。
编辑2:The GNU compiler documentation说,它以C ++的形式扩展了VLA。过去的其他几张海报都发布了VLA起作用的惊奇消息,并询问如何关闭该功能。但是如何打开它?
答案 0 :(得分:2)
在C ++中,您可以使用模板:
#include <iostream>
double determinant(const double (&M)[2][2]){
return M[0][0] * M[1][1] - M[0][1] * M[1][0];
}
template <std::size_t N>
double determinant(const double (&M)[N][N]){
double det=0.0;
double Mminor[N - 1][N - 1];
double sign = 1.0;
for (int i = 0; i < N; i++) {
//get the minor matrix
for (int a = 1; a < N; a++) {
int m=0;
for (int b = 0; b < N; b++) {
if (b != i) {
Mminor[a - 1][m] = M[a][b];
m++;
}
}
}
//add top row element times determinant of its minor
det += sign * M[0][i] * determinant(Mminor);
//swap the sign
sign *= -1.0;
}
return det;
}
int main(){
const double myMatrix[3][3] = {{1,2,3}, {4,5,6}, {3,6,1}};
double okay = determinant(myMatrix);
std::cout << "determinant = " << okay << std::endl;
}