Получение определителя матрицы N x N в C

Я пытался вычислить определитель матрицы N x N, так что это то, что у меня есть до сих пор. Результат, если это -378029970. Я не знаю, что происходит, потому что, если я изменю значение N для размера матрицы, он отлично работает и печатает правильный результат, который равен -20. Я отладил весь скрипт и обнаружил, что проблема заключается в изменении значения N. Я новичок в языке C, поэтому буду признателен, если вы поможете мне с этим. Спасибо!

void getCofactor(int q, int n, int matrix[][n], int temp[][n]) {
    int i = 0;
    int j = 0;
    int p = 0;

    for (int row = 0; row < n; row++) {
        for (int col = 0; col < n; col++) {
            if (row != p && col != q) {
                temp[i][j++] = matrix[row][col];
                if (j == n - 1) {
                    j = 0;
                    i++;
                }
            }
        }
    }
}

int determinante(int n, int matrix[][n]) {
    int D = 0;

    if (n == 1) {
        return matrix[0][0];
    }

    int temp[n][n];
    int sign = 1;

    for (int f = 0; f < n; f++) {
        getCofactor(f, n, matrix, temp);

        D += sign * matrix[0][f] * determinante(n - 1, temp);

        sign = -sign;
    }
    return D;
}

int main() {

    int matrix[3][3] = { { 3, -2, 5}, { -2, 8, 10}, { 3, -2, 4 }};
    int LINHA = 3;

    printf("Determinante: %d", determinante(LINHA, matrix));

    return 0;
}

person Rafael Rossales    schedule 30.08.2020    source источник
comment
Почему тег С++?   -  person klutt    schedule 30.08.2020
comment
Я подумал, что это будет полезно и для изучающих С++.   -  person Rafael Rossales    schedule 30.08.2020
comment
В getCofactor() массив temp имеет ту же ширину строки, что и matrix, но вы не увеличиваете его индексацию, если условие не выполняется. Как вызывающая сторона узнает, сколько строк в temp нужно использовать? Обратите внимание, что неиспользуемые элементы в int temp[n][n]; не были инициализированы.   -  person Weather Vane    schedule 30.08.2020
comment
Я думал, что он уже инициализирован, потому что я передаю LINHA в качестве параметра, поэтому я предположил, что N будет иметь значение LINHA, которое в данном случае равно трем.   -  person Rafael Rossales    schedule 30.08.2020
comment
int temp[n][n]; не инициализирован. Вы ожидаете, что неписаные элементы будут 0? И должны ли приращения j и i быть вне блока кода с условной записью в temp?   -  person Weather Vane    schedule 30.08.2020
comment
@RafaelRossales В общем, вы решаете вещи по-разному в C и C++.   -  person klutt    schedule 30.08.2020
comment
Когда determinante() рекурсирует, он передает массив temp себе в качестве аргумента matrix. Это передается в getCofactor(), который проверяет каждый элемент, однако не каждый элемент массива temp имеет какое-либо значение.   -  person Weather Vane    schedule 30.08.2020
comment
Логика getCofactor() кажется правильной, потому что она отлично работает, когда я изменяю значение N в функции, вызывающей getCofactor(f, N, matrix, temp);. Я думаю, что проблема может быть в инициализации функции, как вы упоминали ранее.   -  person Rafael Rossales    schedule 30.08.2020
comment
@klutt извини, я просто подумал, что это будет полезно.   -  person Rafael Rossales    schedule 30.08.2020
comment
@WeatherVane: неиспользуемые элементы temp не являются проблемой, несовместимые измерения в вызове determinante(n - 1, temp) дают неверный результат. Поведение не определено, и компилятору сложно обнаружить эту ошибку.   -  person chqrlie    schedule 30.08.2020
comment
@chqrlie, чтобы не было неиспользуемых элементов: одна строка и один столбец пропущены.   -  person Weather Vane    schedule 30.08.2020
comment
@WeatherVane: точно! но код в вопросе сохранит эту матрицу n-1 на n-1 в верхнем левом углу temp, оставив последний столбец и последнюю строку неинициализированными. Это не было проблемой, так как геометрия матрицы была исправлена ​​путем создания N глобального. VLA C99 подвержены ошибкам, а 2D VLA должны быть запрещены или реализованы с другой схемой, где размеры являются частью структуры, а не отдельным аргументом.   -  person chqrlie    schedule 30.08.2020
comment
@RafaelRossales Не волнуйся. Здесь это типичная ошибка новичков. В общем, мы относимся к C и C++ как к двум совершенно разным языкам. :)   -  person klutt    schedule 31.08.2020


Ответы (1)


Проблема в том, что temp определяется как int temp[n][n], но размеры этой матрицы несовместимы при передаче в determinante(n - 1, temp).

Вы должны изменить определение temp, чтобы уменьшить размер, и изменить прототип getCofactor, чтобы отразить фактические размеры matrix и temp.

Вот модифицированная версия:

#include <stdio.h>
#include <stdlib.h>

void getCofactor(int q, int n, int matrix[][n], int temp[][n - 1]) {
    int i = 0;
    int j = 0;
    int p = 0;

    for (int row = 0; row < n; row++) {
        for (int col = 0; col < n; col++) {
            if (row != p && col != q) {
                temp[i][j++] = matrix[row][col];
                if (j == n - 1) {
                    j = 0;
                    i++;
                }
            }
        }
    }
}

int determinante(int n, int matrix[][n]) {
    if (n == 1) {
        return matrix[0][0];
    }

    int temp[n - 1][n - 1];
    int sign = 1;
    int D = 0;

    for (int f = 0; f < n; f++) {
        getCofactor(f, n, matrix, temp);
        D += sign * matrix[0][f] * determinante(n - 1, temp);
        sign = -sign;
    }
    return D;
}

int main() {
    int matrix[3][3] = { { 3, -2, 5}, { -2, 8, 10}, { 3, -2, 4 } };
    int LINHA = sizeof(matrix) / sizeof(matrix[0]);

    printf("Determinante: %d\n", determinante(LINHA, matrix));
    return 0;
}
person chqrlie    schedule 30.08.2020