【问题标题】:Recursive Determinant Function Returning Undefined Behavior返回未定义行为的递归行列式函数
【发布时间】:2018-09-04 05:55:18
【问题描述】:

我写了一个递归函数来计算一个行列式。我知道我本可以更有效地完成它,但这不是重点。我有一个名为“det1”的变量,它在递归结束时保存行列式的最终值。 奇怪的是当我在 det 函数中返回这个值时,我得到了完全的垃圾。但是,当我只是简单地打印“det1”时,我得到了答案。这里有什么猜测吗?

int det1 = 0;
int p = 0; 

int det(vector<vector<int> > (&A)){
    if (A.size() != A[0].size()){
        cout << "Determinant Error: non-square matrix. \n";
        return 0; 
    }
    int cF; 
    vector<vector<int> > temp01;
    if (A.size() == 2){
        det1 += (A[0][0]*A[1][1]-A[0][1]*A[1][0]); 
        //cout << "Determinant : " << det1 << "\n";
        int output = det1;                     ///////////////////////////////////////Problem with final return 
        //cout << "Recursion Count : " << p << "\n";  
        //return(output);                        ///////////////////////////////////////
    }else{//extract until a 2x2 is reached
        for (int i = 0; i < A.size(); i++){
             temp01 = extractNext(A,0, i); 
             //printMatrix(temp01); 
             cF = pow(-1, (0)+(i))*A[0][i]; 
             //cout << "Cofactor : " << cF << "\n"; 
             for (int j = 0; j< temp01.size(); j++){
                 temp01[0][j] = cF*temp01[0][j]; //account for cofactor by multiplying it in
             }
             //printMatrix(temp); cout << "\n";
             p++;  
             det(temp01); 
        }
    } 
}

【问题讨论】:

  • 提供Minimal, Complete, and Verifiable example。我们不知道您在 det 中调用的函数是做什么的,以及您使用 det 本身的方式。
  • 全局变量和递归并不是一个令人愉快的组合。
  • 您的函数仅在出现错误时返回一个值。在所有其他情况下,使用(不存在的)返回值是未定义的。
  • 永远不要使用全局变量。同时启用所有编译器警告,并将它们视为错误。
  • 与您的问题无关,但使用pow(-1, ...) 是多余的。

标签: c++ recursion linear-algebra determinants


【解决方案1】:

您不会在所有代码路径上都返回一个值,当您使用一个从未存在的返回值时,这最终会导致未定义的行为。
(一个相当现代的编译器应该警告你这一点。)

您应该从递归中返回行列式,而不是改变全局 - 混合可变状态和递归通常只会导致麻烦。
(这也使您的代码更类似于行列式的数学定义,从而更容易理解和验证。)

有一些小的改动,我会建议类似的东西

int det(const vector<vector<int>> &A)
{
    if (A.size() != A[0].size()){
        cout << "Determinant Error: non-square matrix. \n";
        return 0; 
    }

    if (A.size() == 2)
    {
        return A[0][0] * A[1][1] - A[0][1] * A[1][0]; 
    }
    else
    {
        int determinant = 0;
        int sign = -1;
        for (int i = 0; i < A.size(); i++){
            vector<vector<int>> submatrix = extractNext(A, 0, i);
            sign = -sign;
            int cofactor = sign * A[0][i]; 
            for (int j = 0; j < submatrix.size(); j++){
                submatrix[0][j] = cofactor * submatrix[0][j];
            }
            determinant += det(submatrix);
        }
        return determinant;
    } 
}

【讨论】:

    【解决方案2】:

    您的代码没有返回行列式,因为您没有为其创建返回路径。 你也确实依赖副作用。

    对于 2*2 矩阵,您的代码应该返回正确的值,前提是您只调用一次,但这只是因为它立即采用“if”部分,并一步完成最终计算。 但是,对于 3*3 矩阵,会采用“else”部分。 但请注意,该路径上没有返回,因此您可以期望您的函数返回垃圾。

    要修复它,您需要重写 else 分支,以便计算递归调用返回的值的总和,并为此使用堆栈上的临时变量。 最后,你应该返回这个值。

    【讨论】:

      猜你喜欢
      • 2012-09-26
      • 2013-07-05
      相关资源
      最近更新 更多