cambaluc的个人博客分享 http://blog.sciencenet.cn/u/cambaluc

博文

线性代数(5)C语言找逆矩阵、特征值是整数的简单矩阵

已有 6087 次阅读 2020-7-2 08:19 |个人分类:线性代数|系统分类:教学心得| 线性代数, C语言, 整数逆矩阵, 网络教学

   疫情期间,网络教学,真不是为难学生,只是担心少数学生偷懒抄作业,所以需要随机出一些题让学生学会手工计算,题还不能太难。

    我为每一位同学都随机出了一套计算题,有计算行列式、伴随矩阵、矩阵乘积、化行最简形、求逆矩阵、写线性方程组的通解、求矩阵特征值及对


应特征向量组成的矩阵;让学生按固定格式提交所算出的数,当然出题时我也得调用计算函数输出每位同学对应题目的答案,好批量给分。

    遇到这样的问题,求逆矩阵,得找有逆且逆矩阵也是由简单整数组成的矩阵;求特征值特征向量问题时,所求得数值也需要尽可能简单。

    以下程序实现是实现这一需求的核心程序。

#include "stdafx.h"

#include <math.h>

#include <stdlib.h>

#include <time.h>

//打印一个矩阵

void print_matrix(double *A,int m,int n)

{int i,j;

    for(i=0;i<m;i++)

{ for(j=0;j<n;j++)

  printf("%8.3lf ",A[i*n+j]);

  printf("\n");

}

}

//矩阵乘

void product_matrix(double *A,double *B,double *C,int m,int s,int n)

{int i,j,k;

    for(i=0;i<m*n;i++) C[i]=0;

for(i=0;i<m;i++)

for(j=0;j<n;j++)

for(k=0;k<s;k++)

C[i*n+j]=C[i*n+j]+A[i*s+k]*B[k*n+j];

}

//递归法求行列式

double det(double *A,int n)

{  if(n==1)

       return A[0];

   else 

  { double s=0;  int f=-1,k,i,j;

            double *A1k=new double [(n-1)*(n-1)];

    for(k=0;k<n;k++)

{   for(i=1;i<n;i++)

for(j=0;j<n;j++)

{   if(j<k)

A1k[(i-1)*(n-1)+j]=A[i*n+j];

else if(j>k)

A1k[(i-1)*(n-1)+(j-1)]=A[i*n+j];

}

f=-f;

s=s+f*A[0*n+k]*det(A1k,n-1);

}

delete [] A1k;

        return s;

}

}

//化行最简,记得写这段程序是挺费劲

void ReducedRowEchelonForm(double *B,double *C,int m,int n)

{int i,j,r,c;

double p1,temp;

for(i=0;i<m*n;i++)C[i]=B[i];//C为RREF

    c=0;

    for(r=0;r<m;r++)

{  if(fabs(C[r*n+c])<0.000001)

{  for(i=r+1;i<m;i++)//找非0元

if(fabs(C[i*n+c])>0.000001) break;

   if(i<m)

  for(j=c;j<n;j++) //对换行

{temp=C[r*n+j]; C[r*n+j]=C[i*n+j]; C[i*n+j]=temp; }

}

p1=C[r*n+c];//主元位置

if(fabs(p1)>0.000001)

{   for(j=c;j<n;j++)

C[r*n+j]=C[r*n+j]/p1;//化首1元

  for(i=0;i<m;i++)

  {  if(i==r)continue;

p1=C[i*n+c];

for(j=c;j<n;j++)  //倍加消主元上下方元素

C[i*n+j]=C[i*n+j]-p1*C[r*n+j];

  }

}

else

{r=r-1;}//列全为零,保持在原行,仅列右移

c=c+1;

  }       

}

//求逆矩阵,用的是化行最简的方法,以前也写了求邻接矩阵的方法

int inverse_RREF(double *A,double *Ainv,int n)

{   double *AE=new double [n*n*2];

   double *AE_C=new double [n*n*2];

   int i,j;

   for(i=0;i<n;i++)

   for(j=0;j<n;j++)

{AE[i*n*2+j]=A[i*n+j];

AE[i*n*2+j+n]=0;

}

   for(i=0;i<n;i++)

   AE[i*n*2+i+n]=1;

   ReducedRowEchelonForm(AE,AE_C,n,n*2);

   for(i=0;i<n;i++)

   for(j=0;j<n;j++)

{Ainv[i*n+j]=AE_C[i*n*2+j+n];

}

   delete [] AE,AE_C;

return 1;

}


//这是本博文的核心,其实还是靠穷举

void able_inverse_matrix3(double *A)

{

  //A是一维的,生成9乘Nc=900个数,每9个数是1,2,-1或1开头的可逆阵

  int i1,i2,i3,i4,i5,i6,i7,i8,i9;

  int i, f=0;

  double P[9],Pv[9];

    for(i1=-1;i1<3;i1++)

for(i2=-1;i2<3;i2++)

for(i3=-1;i3<3;i3++)

for(i4=-1;i4<3;i4++)

for(i5=-1;i5<3;i5++)

for(i6=-1;i6<3;i6++)

for(i7=-1;i7<3;i7++)

for(i8=-1;i8<3;i8++)

for(i9=-1;i9<3;i9++)

{P[0]=i1;P[1]=i2;P[2]=i3;P[3]=i4;P[4]=i5;P[5]=i6;P[6]=i7;P[7]=i8;P[8]=i9;

if (det(P,3)==0)

;

else

{inverse_RREF(P,Pv,3);

if(   (Pv[0]-(int)Pv[0])==0

  && (Pv[1]-(int)Pv[1])==0

  && (Pv[2]-(int)Pv[2])==0

  && (Pv[3]-(int)Pv[3])==0

  && (Pv[4]-(int)Pv[4])==0

  && (Pv[5]-(int)Pv[5])==0

  && (Pv[6]-(int)Pv[6])==0

  && (Pv[7]-(int)Pv[7])==0

  && (Pv[8]-(int)Pv[8])==0

              &&(P[0]==1) &&(P[1]==2) &&(P[2]==-1||P[2]==1) )//=897

{for(i=0;i<9;i++)A[i+f]=P[i];

f=f+9;

}

}  

}

}

//测试函数,打出一个可逆矩阵,和手工计算求出的特征值特征向量也是整数的矩阵

void  LinearAlgebra_test0701()

{   double P[9*900];//实际897个

    double A[9],B[9],C[9],D[9],F[9];

int  i,rd;

srand((unsigned)time(NULL));

rd=rand()%897;

able_inverse_matrix3(P);

    for(i=0;i<9;i++)A[i]=P[rd*9+i];

    print_matrix(A,3,3); 

    printf("\n");

//特征值选-1,1,第三个随机。特征向量也取自整数可逆矩阵

C[0]=-1; C[1]=0.; C[2]=0.;

C[3]=0.; C[4]=1 ; C[5]=0.;

C[6]=0.; C[7]=0.; C[8]=rand()%2+2;

    //选一个可逆矩阵,乘对角阵C凑成题目所需的好计算的矩阵

    rd=rand()%897;

    for(i=0;i<9;i++)B[i]=P[rd*9+i];

    product_matrix(B,C,D,3,3,3);

    inverse_RREF(B,F,3);  

    product_matrix(D,F,A,3,3,3);

    print_matrix(A,3,3); 

}

int main(int argc, char* argv[])

{   

    LinearAlgebra_test0701();

return 0;

}

结果:

   1.000    2.000    1.000

  -1.000    2.000    2.000

  -1.000    1.000    1.000


  -5.000    4.000   -4.000

  -8.000    7.000   -4.000

   0.000    0.000    1.000

Press any key to continue



试卷举例:


=====试卷编号1800001

 Linear Algebra Test 2020_05

        Student number:___________     Name:___________

        Student number:__18052288_     Name:___张三__

1.计算下列矩阵的行列式:

┌               ┐

   0   -1    0 

   1   -1   -1 

   0    1    1 

└               ┚

2.计算下列矩阵的伴随矩阵:

┌               ┐

   2    0    2 

   3    2   -1 

   0    2   -2 

└               ┚

3.求下列两矩阵的乘积

┌                     ┐

  -2   -2   -2    3 

  -2   -1   -2    0 

  -2    0    0   -1 

└                    ┚

┌         ┐

   0    0 

   1    3 

   0    3 

  -2    2 

└         ┚

4.把下列矩阵化为行最简形,并写出其秩=____.

┌                            ┐

   1    2    1    2   -2 

  -1   -1    0    3   -2 

   0    2    1    0    0 

└                           ┚

5.求下列矩阵的逆矩阵

┌                ┐

   1    2    1 

  -1   -1   -1 

   1    2    2 

└               ┚

6.设下列矩阵为线性方程组的增广矩阵,最后一列为常数向量,

请化为行最简形,并写出其通解.

┌                             ┐

   1    2   -1    1    2 

   0    1    0    3    3 

   2    1   -1    2   -2 

└                           ┚

7.求下列矩阵的特征值及对应特征向量组成的矩阵

┌               ┐

  -2   -1   -5 

   5    4    7 

  -1   -1    0 

└               ┚

=====1==

{为了不和html冲突,文中的<>号用全角字符替换}



https://blog.sciencenet.cn/blog-797552-1240272.html

上一篇:用Python做一个小学奥数题
下一篇:白头翁
收藏 IP: 114.242.249.*| 热度|

1 李毅伟

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-11-25 21:20

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部