Рекурсивная детерминантная функция, возвращающая неопределенное поведение - PullRequest
0 голосов
/ 04 сентября 2018

Я написал рекурсивную функцию для вычисления определителя. Я знаю, что мог бы сделать это гораздо эффективнее, но здесь дело не в этом. У меня есть переменная с именем «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); 
        }
    } 
}

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Ваш код не возвращает определитель, потому что вы не создали путь возврата для него. Вы тоже полагаетесь на побочные эффекты.

Для матрицы 2 * 2 ваш код должен возвращать правильное значение, при условии, что вы вызываете его только один раз, но только потому, что он сразу принимает часть «если» и выполняет окончательные вычисления за один шаг. Однако для матрицы 3 * 3 берется часть «else». Но обратите внимание, что по этому пути нет возврата, поэтому вы можете ожидать, что ваша функция вернет мусор.

Чтобы исправить это, вам нужно переписать ветвь else так, чтобы вы вычислили сумму значений, возвращаемых рекурсивным вызовом, и использовали для этого временную переменную в стеке. Наконец, вы должны вернуть это значение.

0 голосов
/ 04 сентября 2018

Вы не возвращаете значение для всех путей кода, что в конечном итоге приведет к неопределенному поведению при использовании возвращаемого значения, которое никогда не существовало.
(Довольно современный компилятор должен предупредить вас об этом.)

Вы должны возвращать определитель из рекурсий вместо того, чтобы мутировать глобальное изменяющееся состояние, и рекурсия обычно только приводит к проблемам.
(Это также делает ваш код намного более похожим на математическое определение определителя, что, в свою очередь, делает его более легким для понимания и проверки.)

С некоторыми незначительными изменениями я бы предложил что-то вроде

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;
    } 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...