版本一:
/*********************************************
思路:
对行列式进行初等变换,将某一列化至只有一个非零数
交换完毕之后产生新的数组和维度,递归执行determinant,当维度为2时,
计算该行列式的值,返回这个值
回溯返回最终结果
*********************************************/
#include<stdio.h>
#include<string.h>
int a[100][100];
int divisor = 1;
int determinant(int dimension);
void exchange(int row, int dimension);
int main()
{
int n = 0;
memset(a, 0, sizeof(a));
printf("Please enter the dimension of the determinant:\n");
scanf("%d", &n);
printf("Please enter the determinant:\n");
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
scanf("%d", &a[i][j]);
}
}
int result = determinant(n);
printf("result=%d", result);
result /= divisor;
printf("divisor=%d", divisor);
printf("The result of this determinant is %d\n", result);
return 0;
}
/*********************************************
此处初等变换的思路就是:
总以最后一行为标准值,然后让待交换的行的每一列的
值与标准行的最后一列的值相乘,
将最后的结果除以该值
再将标准行的每一列的值乘以待交换行的最后一列的值,
将最后的结果除以该值
最后将待处理的行的每一列的值减去标准行调整之后的值
这样就可以将待处理行的最后一列的值调整为0
*********************************************/
/*********************************************
为了避免出现最后一行为0的情况,我们先把所有行都加到最后一行上
此外,对于最后一列为0的行,我们无须进行初等变换处理
*********************************************/
int determinant(int dimension)
{
for(int i=dimension-2; i>=0; i--)
{
if(a[i][dimension-1] == 0)
continue;
for(int j=0; j<dimension; j++)
{
a[dimension-1][j] += a[i][j];
}
}
int result;
if(dimension == 2)
{
result = a[0][0]*a[1][1]-a[0][1]*a[1][0];
return result;
}
//该for循环会把最后一列的值处理成只有最后一行的值为非零
//在进行乘运算时,需要先把乘数保存起来,不然在计算时
//其值会被改变,从而影响最终结果
for(int i=dimension-2; i>=0; i--)
{
if(a[i][dimension-1] == 0)
continue;
int sign_1 = a[dimension-1][dimension-1];
int sign_2 = a[i][dimension-1];
for(int j=0; j<dimension; j++)
{
a[i][j] *= sign_1;
a[dimension-1][j] *= sign_2;
}
divisor *= sign_1;
divisor *= sign_2;
exchange(i, dimension);
}
int product = a[dimension-1][dimension-1];
//由于我们选取的总是最后一行的最后一列,故而代数余子式的系数总是为+1
//直接相乘即可
result = product*determinant(dimension-1);
return result;
}
void exchange(int row, int dimension)
{
for(int i=0; i<dimension; i++)
{
a[row][i] -= a[dimension-1][i];
}
}
算法太笨拙,维度或者值稍微大一点的行列式都无法计算
在参考网上的文章之后,我改变了思路,直接按照行列式的按行按列展开来进行计算,公式如下:
测试代码,可将加过输出到文件查看中间结果:
#include<stdio.h>
#include<string.h>
int a[100][100];
int determinant(int a[][100], int dimension);
void spread(int a[][100], int row, int dimension);
void copy_m(int src[][100], int dst[][100], int dimension);
int main(int argc, char* argv[])
{
int summ = 0;
int n = 0;
memset(a, 0, sizeof(a));
//printf("Please enter the dimension of the determinant:\n");
for(int k = strlen(argv[1])-1; k >= 0; k--)
{
int ttmp = 1;
for(int j=0; j<strlen(argv[1])-1-k; j++)
ttmp *= 10;
summ += (argv[1][k]-'0')*ttmp;
}
n = summ;
//printf("Please enter the determinant:\n");
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
summ = 0;
int tmp = 0;
if(argv[i*5+j+2][0] == '-')
{
tmp = 1;
}
for(int k = strlen(argv[i*5+j+2])-1; k >= tmp; k--)
{
int ttmp = 1;
for(int jj=0; jj<strlen(argv[i*5+j+2])-1-k; jj++)
ttmp *= 10;
summ += (argv[i*5+j+2][k]-'0')*ttmp;
// printf("summ=%d\n", summ);
}
if(tmp)
summ = 0-summ;
a[i][j] = summ;
}
}
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
printf("%d ", a[i][j]);
printf("\n");
}
printf("\n\n");
printf("The result of this determinant is %d\n", determinant(a, n));
return 0;
}
int determinant(int a[][100], int dimension)
{
for(int i=0; i<dimension; i++)
{
for(int j=0; j<dimension; j++)
printf("%d ", a[i][j]);
printf("\n");
}
printf("\n\n");
int sum= 0;
//需要构造一个原矩阵的拷贝
int m_copy[100][100];
memset(m_copy, 0, sizeof(m_copy));
copy_m(a, m_copy, dimension);
if(dimension == 2)
{
int result = a[0][0]*a[1][1]-a[0][1]*a[1][0];
return result;
}
for(int i=0; i<dimension; i++)
{
if(a[i][dimension-1]==0)
continue;
spread(a, i, dimension);
int tmp = a[i][dimension-1]*determinant(a, dimension-1);
printf("tmp=%d\n", tmp);
int sign = (i+1+dimension)%2==0?1:(-1);
//sum出了问题
sum += sign*tmp;
printf("sum=%d\n", sum);
copy_m(m_copy, a, dimension);
}
printf("\nreturn here!!\n\n");
return sum;
}
//每次都展开最后一列
//这样可以省去向左缩进的处理
//如果选中了最后一行最后一列
//我们只需要return即可,因为我们不需要对其进行处理
//维度降低1的原数组就是处理后的数组
void spread(int a[][100], int row, int dimension)
{
if(row == dimension-1)
return;
for(int i=row; i<dimension-1; i++)
for(int j=0; j<dimension-1; j++)
a[i][j] = a[i+1][j];
}
void copy_m(int src[][100], int dst[][100], int dimension)
{
for(int i=0; i<dimension; i++)
for(int j=0; j<dimension; j++)
dst[i][j] = src[i][j];
}
最终代码:
/*+++++++++++++++++++
Author: include_heqile
Date: Thur May 31th 2018
School: Hrbust University of Science and Technology
E-mail: [email protected]
++++++++++++++++++++*/
#include<stdio.h>
#include<string.h>
int a[100][100];
int determinant(int a[][100], int dimension);
void spread(int a[][100], int row, int dimension);
void copy_m(int src[][100], int dst[][100], int dimension);
int main()
{
int summ = 0;
int n = 0;
memset(a, 0, sizeof(a));
printf("Please enter the dimension of the determinant:\n");
scanf("%d", &n);
printf("Please enter the determinant:\n");
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
scanf("%d", &a[i][j]);
printf("The result of this determinant is %d\n", determinant(a, n));
return 0;
}
int determinant(int a[][100], int dimension)
{
int sum= 0;
int m_copy[100][100];
memset(m_copy, 0, sizeof(m_copy));
copy_m(a, m_copy, dimension);
if(dimension == 2)
{
int result = a[0][0]*a[1][1]-a[0][1]*a[1][0];
return result;
}
for(int i=0; i<dimension; i++)
{
if(a[i][dimension-1]==0)
continue;
spread(a, i, dimension);
int tmp = a[i][dimension-1]*determinant(a, dimension-1);
int sign = (i+1+dimension)%2==0?1:(-1);
sum += sign*tmp;
copy_m(m_copy, a, dimension);
}
return sum;
}
void spread(int a[][100], int row, int dimension)
{
if(row == dimension-1)
return;
for(int i=row; i<dimension-1; i++)
for(int j=0; j<dimension-1; j++)
a[i][j] = a[i+1][j];
}
void copy_m(int src[][100], int dst[][100], int dimension)
{
for(int i=0; i<dimension; i++)
for(int j=0; j<dimension; j++)
dst[i][j] = src[i][j];
}