不知道为什么,算出来行列式为0,伴随矩阵也全是0,改了两个不一样的版本都这样
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int row;
double hanglieshi(double a[][row],int mi);
double **chushihua(int m,int n){
double **a=NULL;
int i,j;
a=(double **)malloc((m+1)*sizeof(double*));
for(i=0;i<m;i++){
a[i]=(double*)malloc((n+1)*sizeof(double));
}//申请动态内存
printf("请输入矩阵数据:\n");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%lf",&a[i][j]);
}
}
return a;
}
void transpose(double **a,int m,int n){
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++){
printf("%.2lf\t",a[j][i]);
}
printf("\n");
}
}
void bansui(double matrix[row][row],int row){
double tern=0,hls;
int i,j,k,t,n,m,nn=0,mm=0;
double follow[row][row];
for(i=0;i<row;i++){
for(j=0;j<row;j++){
double tempmatrix[row][row];//用于储存每个元素的余子式
n=0;
m=0;
for(k=0;k<row;k++){
for(t=0;t<row;t++){
if(k!=i&&t!=j){
tempmatrix[n][m++]=matrix[k][t];//求余子式,剔除后复制
if(m==row-1){
n++;
m=0;//起到循环作用,到最后一列时到下一行,刷新列
}
}
}
}
tern=hanglieshi(tempmatrix,row-1);//求这一个数值的行列式
follow[nn++][mm]=pow(-1,i+j)*tern;//求代数余子式
if(nn==row){
nn=0;
mm++;
}
}
}
printf("伴随矩阵为:\n");
for(i=0;i<row;i++){
for(j=0;j<row;j++){
printf("%.2lf\t",follow[i][j]);
}
printf("\n");
}
hls=hanglieshi(matrix,row);
if(hls==0){
printf("行列式为0,矩阵不可逆。");
}
else{
printf("逆矩阵为:\n");
for(i=0;i<row;i++){
for(j=0;j<row;j++){
printf("%.2lf\t",follow[i][j]/hls);
}
printf("\n");
}
}
}
double hanglieshi(double a[][row],int mi){//用第一排求行列式值
int i,j,k;
double tern=0,jiangjie[row][row];
if(mi==1){
tern=a[0][0];
} //一阶矩阵直接返还
else if(mi==2){
tern=a[0][0]*a[1][1]-a[0][1]*a[1][0];
}//二阶矩阵进行简便计算
else{//高阶矩阵再次降阶
for(i=0;i<mi;i++){
for(j=0;j<row-1;j++){
for(k=0;k<row-1;k++){
if(k<i)
jiangjie[j][k]=a[j+1][k];
else
jiangjie[j][k]=a[j+1][k+1];
}
}
tern+=pow(-1,i)*a[0][i]*hanglieshi(jiangjie,mi-1);
}
}
return tern;
}
void dayin(double **matrix,int m,int n){
int i,j;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++){
printf("%.2lf\t",matrix[i][j]);
}
printf("\n");
}
}
int main(){
int m,n,caozuo,i,j,flag=0;
double **matrix1=NULL;
printf("欢迎使用矩阵运算器!下面开始初始化需要运算的矩阵。\n");
printf("请输入矩阵的行数:");
scanf("%d",&m); //m为第一个矩阵的行数
printf("请输入矩阵的列数:");
scanf("%d",&n); //n为第一个矩阵的列数
matrix1=chushihua(m,n);
while(flag==0){
printf("请输入对应的数字编号选择您想要进行的操作:\n1.求转置矩阵;\n2.两个矩阵相加;\n3.求两个矩阵的乘积;\n4.求满足条件的方阵A的伴随矩阵A * 、逆矩阵A -1;\n5.退出\n");
scanf("%d",&caozuo);
if(caozuo==1){
printf("转置后矩阵为:\n");
transpose(matrix1,m,n);
}
else if(caozuo==2){
double matrix2[m][n];
printf("请输入与其相加的矩阵数据:\n");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%lf",&matrix2[i][j]);
}
}
printf("相加后矩阵为:\n");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%.2lf\t",matrix1[i][j]+matrix2[i][j]);
}
printf("\n");
}
}
else if(caozuo==3){
int col,k;
double **matrix3=NULL;
printf("与之相乘的矩阵的行数与第一个矩阵列数相同。\n");
printf("请输入与之相乘的矩阵的列数:");
scanf("%d",&col);
matrix3=(double **)malloc((n+1)*sizeof(double*));
for(i=0;i<n;i++){
matrix3[i]=(double*)malloc((col+1)*sizeof(double));
}
matrix3=chushihua(n,col);
double multi[m][col],sum;
printf("相乘后矩阵为:\n");
for(i=0;i<m;i++){
for(j=0;j<col;j++){
sum=0;
for(k=0;k<n;k++){
sum+=matrix1[i][k]*matrix3[k][j];
}//循环相加求和计算单个元素
multi[i][j]=sum;//存入乘积数组
printf("%.2lf\t",multi[i][j]);
}
printf("\n");
}
}
else if(caozuo==4){
int i,j,row;
double tern,hls;
if(m!=n){
printf("原矩阵行列数不等,无法求伴随矩阵及逆矩阵,请输入新矩阵的行列数:\n");
scanf("%d",&row);
double follow[row][row],matrix4[row][row];
printf("请输入矩阵数据:\n");
for(i=0;i<row;i++){
for(j=0;j<row;j++){
scanf("%lf",&matrix4[i][j]);
}
}
bansui(matrix4,row);
}
else{
row=m;
double matrix4[row][row];
for(i=0;i<row;i++){
for(j=0;j<row;j++){
matrix4[i][j]=matrix1[i][j];
}
}
bansui(matrix4,row);
}
}
else if(caozuo==5){
exit(0);
}
else{
printf("错误");
}
}
}
无报错,只是答案不对
希望能帮我找出错误,在原有代码上改正,不要通篇换思路,不要给现成代码,谢谢(修改了一些小错,和刚发的时候有点区别,但结果没变)
#include<stdio.h>
#include<stdlib.h>
int n,m;
float **a;//运用二重指针,避免二维数组做函数参数时长度未定情况 ;但是要先申请空间
void input() {
int i,j;
printf("请输入行数:");
scanf("%d",&n);
printf("请输入列数:");
scanf("%d",&m);
printf("请输入元素:\n");
a=(float **)malloc(sizeof(float *)*n);//申请行空间
for(i=0; i<n; i++) {
a[i]=(float *)malloc(sizeof(float)*m);//申请列空间
printf("第%d行:",i+1);
for(j=0; j<m; j++) {
scanf("%f",&a[i][j]);
}
}
}
void output(float **c,int p,int q) {
int i,j;
for(i=0; i<p; i++) {
printf("第%d行:",i+1);
for(j=0; j<q; j++) {
printf("%.1f ",c[i][j]);
}
printf("\n");
}
printf("\n");
}
void transform() {
int i,j;
float b[m][n];
for(i=0; i<n; i++) {
for(j=0; j<m; j++) {
b[j][i]=a[i][j];
}
}
for(i=0; i<m; i++) {//转置行数与列数互换
for(j=0; j<n; j++) {
printf("%.1f ",b[i][j]);
}
printf("\n");
}
printf("\n");
}
void add() {
int i,j;
float c[n][m],d[n][m];//相加维数相同;不需要再定义阶数
printf("请输入元素:\n");
for(i=0; i<n; i++) {
printf("第%d行:",i+1);
for(j=0; j<m; j++) {
scanf("%f",&c[i][j]);
}
}
for(i=0; i<n; i++) {
for(j=0; j<m; j++) {
d[i][j]=a[i][j]+c[i][j];
}
}
printf("相加后的矩阵为:\n");
for(i=0; i<n; i++) {
printf("第%d行:",i+1);
for(j=0; j<m; j++) {
printf("%.1f ",d[i][j]);
}
printf("\n");
}
}
void multiply() {
int i,j,k,r;
float c[m][r],d[n][r];
printf("请输入列数:");//相乘:第一个矩阵列数与第二个矩阵行数相同
scanf("%d",&r);
printf("请输入元素:\n");
for(i=0; i<m; i++) {
printf("第%d行:",i+1);
for(j=0; j<r; j++) {
scanf("%f",&c[i][j]);
}
}
for(i=0; i<n; i++) {
for(j=0; j<r; j++) {
for(k=0; k<m; k++) {
d[i][j]+=a[i][k]*c[k][j];
}
}
}
printf("相乘后的矩阵为:\n");
for(i=0; i<n; i++) {
printf("第%d行:",i+1);
for(j=0; j<r; j++) {
printf("%.1f ",d[i][j]);
}
printf("\n");
}
}
float determinant(float **c,int n) {//按第一行完全展开式计算|A|
float det,t,**temp1;
temp1=(float **)malloc(sizeof(float *)*(n-1));//为储存降阶矩阵开辟空间
for(int p=0; p<n-1; p++) {
temp1[p]=(float *)malloc(sizeof(float)*(n-1));
}
if(n==2) {
det=c[0][0]*c[1][1]-c[0][1]*c[1][0];//作为终止条件; 二阶矩阵直接计算 ;
} else {
for(int i=0; i<n; i++) {
for(int j=0; j<n-1; j++) {//记录第一行元素对应余子式的矩阵
for(int k=0; k<n-1; k++) {
temp1[j][k]=c[j+1][(k>=i)?k+1:k];//若列数小于i则不变;若列数大于等于i则向后移动一列;从而记录余子式的矩阵
}
}
t=determinant(temp1,n-1);//递归计算
if(i%2==0) {//判断余子式的正负;与第一行元素相乘;相加得行列式
det+=c[0][i]*t;
} else {
det-=c[0][i]*t;
}
}
}
return det;
}
float **adjoint(float **c,int n) {//计算每一行每一列的每个元素所对应的余子式,组成A*
float **temp2,**adj;
if(n==2) {
adj=(float **)malloc(sizeof(float *)*n); //为n阶伴随矩阵开辟空间
for(int p=0; p<n; p++) {
adj[p]=(float *)malloc(sizeof(float)*n);
}
adj[0][0]=a[1][1];
adj[0][1]=(-1)*a[1][0];
adj[1][0]=(-1)*a[0][1];
adj[1][1]=a[0][0];
} else {
temp2=(float **)malloc(sizeof(float *)*(n-1)); //为n-1阶矩阵开辟空间
for(int p=0; p<n-1; p++) {
temp2[p]=(float *)malloc(sizeof(float)*(n-1));
}
adj=(float **)malloc(sizeof(float *)*n); //为n阶伴随矩阵开辟空间
for(int p=0; p<n; p++) {
adj[p]=(float *)malloc(sizeof(float)*n);
}
for(int i=0; i<n; i++) {//每行
for(int j=0; j<n; j++) {//每列
for(int k=0; k<n-1; k++) {//n-1阶矩阵
for(int t=0; t<n-1; t++) {
temp2[k][t]=c[(k>=i)?k+1:k][(t>=j)?t+1:t];//剔除元素所在行与列之后的矩阵
}
}
adj[j][i]=determinant(temp2,n-1);//计算代数余子式Aji为 转置 后的
if((i+j)%2==1) {//判断符号(-1)^(i+j)
adj[j][i]=-adj[j][i];
}
}
}
}
return adj;
}
int main() {
float z;
float **adj,**bt;
int flag=1;
do {
printf("初始化矩阵:1\n");
printf("打印矩阵: 2\n");
printf("矩阵转置: 3\n");
printf("矩阵相加: 4\n");
printf("矩阵相乘: 5\n");
printf("矩阵求逆: 6\n");
printf("伴随矩阵: 7\n");
printf("退出程序: 0\n");
int o;
printf("请选择功能:");
scanf("%d",&o);
switch(o) {
case 1:
printf("请输入矩阵内容:\n");
input();
break;
case 2:
printf("矩阵内容为:\n");
output(a,n,m);
break;
case 3:
printf("转置后的矩阵为:\n");
transform();
break;
case 4:
printf("请输入新矩阵:\n");
add();
break;
case 5:
printf("请输入新矩阵:\n");
multiply();
break;
case 6:
bt=adjoint(a,n);
z=determinant(a,n);//返回行列式的值
if(z==0) {//判断是否可逆
printf("\n矩阵不可逆!!\n");
} else {
printf("逆矩阵为:\n");
for(int i=0; i<n; i++) {
printf("第%d行:",i+1);
for(int j=0; j<n; j++) {
printf("%.1f ",bt[i][j]/z);//A逆==A*/|A|
}
printf("\n");
}
}
break;
case 7:
printf("伴随矩阵为:\n");
bt=adjoint(a,n);
output(bt,n,n);
break;
case 0:
flag=0;
printf("感谢使用!!");
break;
default:
printf("\n输入错误,请重新输入!!!!\n\n");
break;
}
} while(flag);
}
受朋友之托来看看这个问题,代码大概调了一下,因为时间有限,就现在发现的问题先说一说
这个不是核心问题。main 函数里的 if ... elseif ... else
分支可以改成 switch 的形式。不过形式不重要,重要的是,最好把每一个操作封装成函数逻辑,这样有两个好处:一是局部变量不会混淆,不需要定义 matrix2
、matrix3
、matrix4
这些东西;二是可以让 main 里面的逻辑更清晰,甚至可以通过函数指针的形式直接把多分支替换成数组寻址(找到函数再调用)
这个问题比较重要,也可能就是这里引起的问题。问题是 void bansui(double matrix[row][row],int row)
这个函数声明。如果没有前面全局的 row
,这个声明会报错。这里的 row
其实是最上面的全局 row
,其值为 0,也就是说声明中是 matrix[0][0]
,而不是理想中的第二个参数的 row
值。加一段代码就可以看出来
int row;
void printGlobalRow() {
printf("global row is %d\n", row);
}
//...
void bansui(double matrix[row][row], int row)
{
printGlobalRow(); // 输出 0
printf("local row is %d\n", row); // 输出输入的矩阵大小
// ...
}
所以在定义函数的时候,如果不能确定二维数组参数的列大小,应该使用 **
指针来传递,并在程序中去计算,就有点像初始化的时候那样。像 transpose
这样使用就没毛病。
算是个建议,尽量避免变量作用域“贯穿”。意思就是,尽量避免使用全局变量,避免 switch 或者在复杂的 if 分支中使用函数定义的局部变量。避免使用全局变量比较好办,把变更声明为局部的再通过参数带着走行就。避免 switch 或者 if 分支中的贯穿,可能需要提取子函数。不用担心内存的问题,这点数量量对内存来说毫无压力。如果确实遇到大数据需要考虑优化的情况再具体事情具体说。
最后,CSDN 好久没来了,如果要找我可以上思否 (SegmentFault)
不行没有注释,参数理解起来费劲
我现在写!望采纳!!点击该回答右侧的“采纳”按钮即可采纳!!
可以参考下面的:
https://blog.csdn.net/weixin_45987327/article/details/125405983
首先,程序在调用函数 hanglieshi 时传入的第二个参数 mi 的值为矩阵的行数,但是在 hanglieshi 函数内部,使用了全局变量 row 代替了 mi。这意味着,如果程序在调用 hanglieshi 函数时行数与全局变量 row 的值不同,则会出现 bug。
此外,程序中存在一些其他的问题,导致程序无法正常执行。下面是一些建议:
1.在求解行列式时,应该将每一个数值的行列式与行列式的积相加。这样才能得到正确的行列式值。
2.在计算伴随矩阵时,应该使用数学知识来求解。伴随矩阵的第 (i, j) 个元素应该为代数余子式的 (j, i) 个元素,除以行列式的值。
3.在计算逆矩阵时,应该先求出行列式的值,然后求出伴随矩阵,再将伴随矩阵的每一个元素除以行列式的值。
望采纳。
行列式为0,伴随矩阵全部为0的情况可能是由于矩阵不可逆导致的。一般来说,如果一个矩阵的行列式为0,则这个矩阵不可逆,伴随矩阵也为0。
可以尝试在程序中加入检查行列式是否为0的代码,如果为0,就输出“矩阵不可逆”的信息。可以在计算行列式值的地方加入判断条件,如果行列式值为0,就输出矩阵不可逆的信息。
例如:
```
hls=hanglieshi(matrix,row);
if(hls==0){
printf("行列式为0,矩阵不可逆。");
}
```希望这些建议能帮到您。