将矩阵逐步化简至行最简形并求秩
将矩阵逐步化简至行最简形并求秩
支持分数,显示步骤,9x9以内矩阵。
【注意】:由于实时录入字符,请务必用【英文输入法】,且用空格代替回车,【输矩阵时不要按回车(输行列数时可以)】,输错请重新运行程序。
截图:
/************************
@author:citrus
@date:2021/1/11
*************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define N 9
int isPrime(int x);
int m=-1,n=-1;
typedef struct fraction
{
int numerator;
int denominator;
}Fraction;
Fraction reduce(Fraction f)
{
if(f.numerator==0)
{
f.denominator=1;
return f;
}
else if(f.denominator!=0)
{
int sign=f.numerator/abs(f.numerator);
f.numerator=abs(f.numerator);
int gcd=1;
for(int i=2;i<=(f.numerator<f.denominator?f.numerator:f.denominator);i++)
{
if(f.numerator%i==0&&f.denominator%i==0)gcd=i;
}
f.numerator=f.numerator/gcd*sign;
f.denominator=f.denominator/gcd;
return f;
}
}
Fraction plus(Fraction f1,Fraction f2)
{
Fraction f3={f1.numerator*f2.denominator+f1.denominator*f2.numerator,f1.denominator*f2.denominator};
return reduce(f3);
}
Fraction minus(Fraction f1,Fraction f2)
{
Fraction f3={f1.numerator*f2.denominator-f1.denominator*f2.numerator,f1.denominator*f2.denominator};
return reduce(f3);
}
Fraction time(Fraction f1,Fraction f2)
{
Fraction f3={f1.numerator*f2.numerator,f1.denominator*f2.denominator};
return reduce(f3);
}
Fraction divide(Fraction f1,Fraction f2)
{
int sign=f2.numerator/abs(f2.numerator);
Fraction f3={f1.numerator*f2.denominator*sign,f1.denominator*abs(f2.numerator)};
return reduce(f3);
}
Fraction reciprocal(Fraction f)
{
if(f.numerator!=0&&f.denominator!=0)
{
int sign=f.numerator/abs(f.numerator);
Fraction f0={f.denominator*sign,abs(f.numerator)};
return reduce(f0);
}
}
Fraction absolution(Fraction f)
{
Fraction f0=f;
f0.numerator=abs(f0.numerator);
return reduce(f0);
}
int isPrime(int x)
{
if(x>=-1&&x<=1)return 0;
x=abs(x);
for(int i=2;i<x;i++)
{
if(x%i==0)return 0;
}
return 1;
}
void initMartrix(Fraction mar[][N])
{
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
mar[i][j].numerator=0;
mar[i][j].denominator=1;
}
}
}
void printMartrix(Fraction mar[][N],char *str)
{
printf("%s ==================================================\n",str);
for(int i=0;i<m;i++)
{
printf("\n");
for(int j=0;j<n;j++)
{
if(mar[i][j].denominator==1)printf("%4d ",mar[i][j].numerator);
else printf("%3d/%-2d ",mar[i][j].numerator,mar[i][j].denominator);
}
printf("\n");
}
puts("");
}
void printFullMartrix(Fraction mar[][N],char *str)
{
printf("%s ==================================================\n",str);
for(int i=0;i<m;i++)
{
printf("\n");
for(int j=0;j<n;j++)
{
printf("%3d/%-2d ",mar[i][j].numerator,mar[i][j].denominator);
}
printf("\n");
}
puts("");
}
void inputMartrix(Fraction mar[][N])
{
printf("请输入%d×%d矩阵(支持分数,仅以一空格隔开,不用回车,[实时录入],自动结束,请勿输错,请先切换至EngIME,如-12/5 7 2/3 ):\n",m,n);
int t=0;
int sign=1;
int tofm=0;
int p=1;
int shouldentercount;
int entercount=0;
while(p<=m*n)
{
shouldentercount=(p-1)/n;
if(entercount==shouldentercount)
{
puts("");
entercount++;
}
char c=getche();
if(c=='-')
{
sign=-1;
}
else if(c>='0'&&c<='9')
{
t=t*10+c-'0';
}
else if(c=='/')
{
mar[(p-1)/n][(p-1)%n].numerator=sign*t;
t=0;
sign=1;
tofm=1;
}
else if(c==' ')
{
if(tofm==1)
{
mar[(p-1)/n][(p-1)%n].denominator=sign*t;
}
else
{
mar[(p-1)/n][(p-1)%n].numerator=sign*t;
}
t=0;
sign=1;
tofm=0;
p++;
}
else if(c==-95||c==-94)
{
puts("\n错误,请结束并切换至EngIME.");
}
}
}
void ktimesRowi(Fraction mar[][N],int k,int i)
{
if(i>=1&&i<=m&&k!=0)
{
i--;
Fraction f={k,1};
for(int x=0;x<n;x++)
{
mar[i][x]=time(mar[i][x],f);
}
}
}
void FractionktimesRowi(Fraction mar[][N],Fraction k,int i)
{
if(i>=1&&i<=m)
{
i--;
for(int x=0;x<n;x++)
{
mar[i][x]=time(mar[i][x],k);
}
}
}
void simplifyRowi(Fraction mar[][N],int i)
{
if(i>=1&&i<=m)
{
i--;
Fraction reciprocalOfNonZeroFirstElem;
int gotNZFE=0;
int printed=0;
for(int x=0;x<n;x++)
{
if(mar[i][x].numerator!=0)
{
if(gotNZFE==0)
{
gotNZFE=1;
reciprocalOfNonZeroFirstElem=reciprocal(mar[i][x]);
}
if(gotNZFE==1)
{
if(!(reciprocalOfNonZeroFirstElem.numerator==1&&reciprocalOfNonZeroFirstElem.denominator==1))
{
if(printed==0)
{
if(reciprocalOfNonZeroFirstElem.denominator==1&&reciprocalOfNonZeroFirstElem.numerator>0)
printf("r%d × %d",i+1,reciprocalOfNonZeroFirstElem.numerator);
else if(reciprocalOfNonZeroFirstElem.denominator==1&&reciprocalOfNonZeroFirstElem.numerator<0)
printf("r%d × (%d)",i+1,reciprocalOfNonZeroFirstElem.numerator);
else if(reciprocalOfNonZeroFirstElem.denominator!=1&&reciprocalOfNonZeroFirstElem.numerator>0)
printf("r%d × %d/%d",i+1,reciprocalOfNonZeroFirstElem.numerator,reciprocalOfNonZeroFirstElem.denominator);
else if(reciprocalOfNonZeroFirstElem.denominator!=1&&reciprocalOfNonZeroFirstElem.numerator<0)
printf("r%d × (%d/%d)",i+1,reciprocalOfNonZeroFirstElem.numerator,reciprocalOfNonZeroFirstElem.denominator);
printed=1;
}
mar[i][x]=time(mar[i][x],reciprocalOfNonZeroFirstElem);
}
}
}
}
if(printed==1)printMartrix(mar,"");
}
}
void RowiminusRowj(Fraction mar[][N],int i,int j)
{
if(i>=1&&i<=m&&j>=1&&j<=m)
{
printf("r%d - r%d",i,j);
i--;j--;
for(int x=0;x<n;x++)
{
mar[i][x]=minus(mar[i][x],mar[j][x]);
}
printMartrix(mar,"");
}
}
void RowiminusFractionkRowj(Fraction mar[][N],int i,int j,Fraction f){
if(i>=1&&i<=m&&j>=1&&j<=m)
{
if(f.denominator==1&&f.numerator==1)printf("r%d - r%d",i,j);
if(f.denominator==1&&f.numerator==-1)printf("r%d + r%d",i,j);
else if(f.denominator==1&&f.numerator>1)printf("r%d - %d × r%d",i,f.numerator,j);
else if(f.denominator==1&&f.numerator<-1)printf("r%d + %d × r%d",i,abs(f.numerator),j);
else if(f.denominator!=1&&f.numerator>0)printf("r%d - %d/%d × r%d",i,f.numerator,f.denominator,j);
else if(f.denominator!=1&&f.numerator<0)printf("r%d + %d/%d × r%d",i,abs(f.numerator),f.denominator,j);
i--;j--;
for(int x=0;x<n;x++)
{
mar[i][x]=minus(mar[i][x],time(f,mar[j][x]));
}
printMartrix(mar,"");
}
}
void swapRowiRowj(Fraction mar[][N],int i,int j)
{
if(i>=1&&i<=m&&j>=1&&j<=m)
{
printf("r%d <--> r%d",i,j);
i--;j--;
Fraction temp;
for(int x=0;x<n;x++)
{
temp=mar[i][x];
mar[i][x]=mar[j][x];
mar[j][x]=temp;
}
printMartrix(mar,"");
}
}
void sortRowByElemrc(Fraction mar[][N],int r,int c)
{
if(r>=1&&r<=m&&c>=1&&c<=n)
{
r--;c--;
for(int i=r;i<m-1;i++)
{
for(int j=i+1;j<m;j++)
{
if(mar[i][c].numerator==0&&mar[j][c].numerator!=0)
{
swapRowiRowj(mar,i+1,j+1);
}
}
}
}
}
int haveNonZeroElemFromRowpInColumnq(Fraction mar[][N],int p,int q)
{
if(p>=1&&p<=m&&q>=1&&q<=n)
{
p--;q--;
int havenonzero=0;
for(int x=p;x<m;x++)
{
if(mar[x][q].numerator!=0)
{
havenonzero=1;
}
}
return havenonzero;
}
}
void simplifyToSimplestRowForm(Fraction mar[][N])
{
int k=1;
int i=1;
while(i>=1&&i<=m&&k>=1&&k<=n)
{
if(haveNonZeroElemFromRowpInColumnq(mar,i,k)==1)
{
for(int q=i;q<=m;q++)
{
simplifyRowi(mar,q);
}
sortRowByElemrc(mar,i,k);
for(int q=i+1;q<=m;q++)
{
if(mar[q-1][k-1].numerator!=0)RowiminusRowj(mar,q,i);
}
i++;
k++;
}
else if(haveNonZeroElemFromRowpInColumnq(mar,i,k)==0)k++;
}
k=1;
i=1;
while(i>=1&&i<=m&&k>=1&&k<=n)
{
if(haveNonZeroElemFromRowpInColumnq(mar,i,k)==1)
{
for(int q=1;q<i;q++)
{
if(mar[q-1][k-1].numerator!=0)
{
RowiminusFractionkRowj(mar,q,i,divide(mar[q-1][k-1],mar[i-1][k-1]));
}
}
i++;
k++;
}
else if(haveNonZeroElemFromRowpInColumnq(mar,i,k)==0)k++;
}
}
int rank(Fraction mar[][N])
{
int r=m;
for(int i=m-1;i>=0;i--)
{
int fullrowzero=1;
for(int j=0;j<n;j++)
{
if(mar[i][j].numerator!=0)fullrowzero=0;
}
if(fullrowzero==1)r--;
}
return r;
}
int main(void)
{
Fraction mar[N][N];
char c;
do
{
initMartrix(mar);
int t=0;
do
{
if(!t)printf("\n请输入m×n矩阵的m n(1<=m,n<=9):");
scanf("%d %d",&m,&n);
t++;
}while(!(m>=1&&m<=9&&n>=1&&n<=9)&&printf("请重输:"));
inputMartrix(mar);
printMartrix(mar,"\n原矩阵:");
simplifyToSimplestRowForm(mar);
printMartrix(mar,"行最简形:");
puts("=======================================");
printf("R=%d\n\n",rank(mar));
printf("是否继续(Y/y)?");
c=getche();
}while(c=='Y'||c=='y');
return 0;
}