I am making a program for calculating a determinant of a matrix in C and I want to do so by using vectors, after this I will make a program that inverts a matrix, but I will do that afterwards. I don't have much experience using vectors, so I assume that I'm making a stupid mistake, here is my function:
#include<iostream>
#include<vector>
#include<cmath>
#include<cstdlib>
int determinant(std::vector<std::vector<int>>& matrix, int x, int y) {
std::vector<std::vector<int>> minor;
int det, position;
if(x != y)
{
return 0;
}
switch (x)
{
case 2:
return (matrix[0][0]*matrix[1][1])-(matrix[1][0]*matrix[0][1]);
break;
case 1:
return matrix[0][0];
break;
}
for(postion= 0; position< x; position )
{
int temp;
for(uint8_t i = 1; i < x; i )
for(uint8_t j = 0; j < y; j )
if(j != position)
minor[i-1][j] = matrix[i][j];
det = pow((-1), position 2) * matrix[0][position]*determinant(minor, x-1, y-1);
}
return det;
main()
{
srand(time(0));
int input;
int row, col;
std::cin >> row >> col;
std::vector<std::vector<int>> matrix;
for(uint8_t i = 0; i < row; i )
{
std::vector<int> temp;
for(uint8_t j = 0; j < col; j )
{
std::cin >> input;
temp.push_back(input);
}
matrix.push_back(temp);
}
std::cout << std::endl << "Determinant: " << determinant(matricx, row, col);
I tried making it work by using minor.pushback(matrix[i][j]), but I get an error message saying that argument types are (int) and I also get an error message saying "no instance of overload function" Also if the name of a variable doesnt match somewhere, I was changing it manually, so maybe I forgot to change somewhere, because I named them in my native language, just so You don't think that that is an issue.
CodePudding user response:
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
int determinant(std::vector<std::vector<int>>& matrix) {
int n = matrix. Size();
if(n == 1)
return matrix[0][0];
else if(n == 2)
return matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0];
else{
int det = 0, position;
for(position = 0; position < n; position){
std::vector<std::vector<int>> minor;
for(int i = 1; i < n; i){
std::vector<int> row;
for(int j = 0; j < n; j){
if(j != position)
row.push_back(matrix[i][j]);
}
minor.push_back(row);
}
det = pow(-1.0, position)*matrix[0][position]*determinant(minor);
}
return det;
}
}
int main()
{
int input;
int n;
std::cin >> n;
std::vector<std::vector<int>> matrix;
for(int i = 0; i < n; i )
{
std::vector<int> temp;
for(int j = 0; j < n; j )
{
std::cin >> input;
temp.push_back(input);
}
matrix.push_back(temp);
}
std::cout << std::endl << "Determinant: " << determinant(matrix);
return 0;
}
Above is my revision of your code.
Basically, there are lots of problems in your code.
(1) There are some typos. Please use your compiler to help you revise them.
(2) You use srand(time(0));, but not include . Also, you don't use any random number generator, so I think this line is unnecessary.
(3) You don't specify the size of minor, but try to access the element such as minor[i-1][j]. This will lead to out of range access of vector. I suggest you to put the declaration of minor in the loop body of position and use push_back to insert elements.
Of course, you can also specify the size of minor by vector<vector> minor(x-1), but you should also put this declaration after the switch statement.
In fact, it is meaningless to compute the determinant of a non-square matrix.
So, you can assume the size must be nxn and only one parameter for the size is sufficient.
Also, the size of matrix is embedded in vector, so using vector<vector> matrix as parameter of determinant is sufficient.
Hope this will help you.
CodePudding user response:
Here's a possible implementation:
- Do some sanity checks for empty and non-square matrices.
- Do a base case check for matrices of size 1.
- For every column
col
:- get the the submatrix
n
(m
without the elements from row0
and columncol
), - compute the intermediate result,
m[0][col] * determinant(n)
, - add or subtract that intermediate result depending on
col
being even or odd.
- get the the submatrix
int determinant(const matrix_t& m) {
if (m.empty()) {
throw std::runtime_error{ "Matrix is empty.\n" };
}
if (m.size() != m[0].size()) {
throw std::runtime_error{ "Matrix is not square.\n" };
}
if (m.size() == 1) {
return m[0][0];
}
int det{};
for (int col{0}; col < m[0].size(); col) {
matrix_t n{ get_matrix_without_row_0_and_col_n(m, col) };
int tmp{ m[0][col] * determinant(n) };
auto col_is_even = [&col]() { return (col % 2) == 0; };
if (col_is_even()) {
det = tmp;
} else {
det -= tmp;
}
}
return det;
}
In order to build the submatrix n
:
- Define a matrix of size
m.size() -1
timem.size() - 1
. - Fill its cells with values from
m[i][j]
, considering that:i
should start at index 1,j
cannot be equals tocol
.
matrix_t get_matrix_without_row_0_and_col_n(const matrix_t& m, int col) {
matrix_t ret(m.size() - 1, row_t(m.size() - 1));
std::ranges::for_each(ret, [&m, &col, i=1, j=0](row_t& row) mutable {
std::ranges::generate(row, [&m, &col, &i, &j]() {
if (j == col) {
advance_to_next_cell_in_matrix(m, i, j);
}
auto ret{ m[i][j] };
advance_to_next_cell_in_matrix(m, i, j);
return ret;
});
});
return ret;
}