matematykaszkolna.pl
Funkcja Benny: Muszę napisać funkcję dopełnienie algebraiczne, korzystając z funkcji wyznacznik. Mam zwrócić dopełnienie algebraiczne elementu A[i][j] macierzy stopnia n. float dopalg(int i, int j, int n, float A[100][100]) { float tab[99][99]; int l=0,z=0; for(int k=0; k<n−1;k++) { for(int d=0; d<n−1; d++) { if(k!=i−1 && d!=j) { tab[l][z]=A[k][d]; z++; } } l++; z=0; } float m=A[i][j]; return(m*pow(−1,i+j)*wyznacznik(n−1,tab[99][99])); } Dobrze?
7 sty 20:27
Mariusz: #include <iostream> #include <complex> #include <conio.h> using namespace std; complex<double> det(complex<double>**,int,double); void swapcols(int,int,int,complex<double>**,complex<double>**); void cramer(complex<double>**,int,double,complex<double>*); void gauss(complex<double>**,int,double,complex<double>*); void inverse(complex<double>**,int,double,int&); void multiply(complex<double>**,complex<double>**,complex<double>**,int,int,int); void ludcmp(complex<double>**,int,int*,complex<double>&); void lubksb(complex<double>**,int,int*,complex<double>*); int main(){ char esc; int i,j,n; int err; int c; int* indx; complex<double> **A,**B,**C,*X; double eps=1e−12; complex<double> d; //clrscr(); do{ cout<<"Rozwiazywanie ukladow rownan liniowych "<<endl; cout<<"1 Metoda Cramera "<<endl; cout<<"2 Metoda Gaussa "<<endl; cout<<"3 Metoda X=A(−1)*B "<<endl; cout<<"4 Metoda rozkladu LU "<<endl; cout<<endl; cin>>c; cout<<endl; cout.precision(12); switch(c){ case 1:{ cout<<"Podaj n="; cin>>n; A=new complex<double>*[n+2]; for(i=0;i<=n+1;i++) A[i]=new complex<double>[n+2]; X=new complex<double>[n+1]; for(i=1;i<=n;i++) for(j=1;j<=n+1;j++){ cout<<"a["<<i<<"]["<<j<<"]="; cin>>A[i][j]; } cramer(A,n,eps,X); if(X[0]!=0.0) for(i=1;i<=n;i++) cout<<"X["<<i<<"]="<<X[i]<<endl; cout<<endl; for(i=0;i<=n+1;i++) delete[] A[i]; delete[] A; delete[] X; break; } case 2:{ cout<<"Podaj n="; cin>>n; A=new complex<double>*[n+2]; for(i=0;i<=n+1;i++) A[i]=new complex<double>[n+2]; X=new complex<double>[n+1]; for(i=1;i<=n;i++) for(j=1;j<=n+1;j++){ cout<<"A["<<i<<"]["<<j<<"]="; cin>>A[i][j]; } gauss(A,n,eps,X); for(i=1;i<=n;i++) cout<<"X["<<i<<"]="<<X[i]<<endl; cout<<endl; for(i=0;i<=n+1;i++) delete[] A[i]; delete[] A; delete[] X; break; } case 3:{ cout<<"Podaj n="; cin>>n; A=new complex<double>*[n+1]; for(i=0;i<=n;i++) A[i]=new complex<double>[n+1]; B=new complex<double>*[2]; for(i=0;i<=n;i++) B[i]=new complex<double>[2]; C=new complex<double>*[2]; for(i=0;i<=n;i++) C[i]=new complex<double>[2]; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ cout<<"A["<<i<<"]["<<j<<"]="; cin>>A[i][j]; } cout<<"B["<<i<<"]="; cin>>B[i][1]; } inverse(A,n,eps,err); multiply(C,A,B,n,1,n); if(err==0) for(i=1;i<=n;i++) cout<<"X["<<i<<"]="<<C[i][1]<<endl; for(i=0;i<=n;i++) delete[] A[i]; delete[] A; for(i=0;i<=1;i++) delete[] B[i]; delete[] B; for(i=0;i<=1;i++) delete[] C[i]; delete[] C; break; } case 4:{ cout<<"Podaj n="; cin>>n; A=new complex<double>*[n+2]; for(i=0;i<=n+1;i++) A[i]=new complex<double>[n+2]; X=new complex<double>[n+1]; indx=new int[n+1]; for(i=1;i<=n;i++) for(j=1;j<=n+1;j++){ cout<<"A["<<i<<"]["<<j<<"]="; cin>>A[i][j]; } ludcmp(A,n,indx,d); for(i=1;i<=n;i++) X[i]=A[i][n+1]; if(d!=0.0){ lubksb(A,n,indx,X); for(i=1;i<=n;i++) cout<<"X["<<i<<"]="<<X[i]<<endl; cout<<endl; } for(i=0;i<=n+1;i++) delete[] A[i]; delete[] A; delete[] X; delete[] indx; break; } default: cout<<"Wprowadz liczbe od 1 do 4 "<<endl; } esc=getch(); } while (esc!=27); return 0; } void inverse(complex<double>** A,int n,double eps,int& blad){ int i,j,k,l; complex<double> maxA,d,e; int* M; int b; M=new int [n+1]; b=0; for(i=1;i<=n;i++){ maxA=0.0; for(j=i;j<=n;j++){ d=A[j][i]; if(abs(maxA)<abs(d)){ maxA=d; k=j; } } if(abs(maxA)<eps) b=1; if(!b){ M[i]=k; A[k][i]=1.0; for(j=1;j<=n;j++){ d=complex<double>(A[k][j]/maxA); A[k][j]=A[i][j]; A[i][j]=d; } for(j=1;j<=n;j++) if(j!=i){ d=A[j][i]; A[j][i]=0.0; for(l=1;l<=n;l++){ e=d*A[i][l]; A[j][l]−=e; } } } } if(!b){ for(i=n;i>=1;i−−){ k=M[i]; if(k!=i) for(j=1;j<=n;j++){ d=A[j][i]; A[j][i]=A[j][k]; A[j][k]=d; } } } blad=b; delete[] M; } void multiply(complex<double>** D,complex<double>** A,complex<double>** B,int m,int p,int n){ int i,j,k; complex<double> s; for(i=1;i<=m;i++){ for(k=1;k<=p;k++) { s=0.0; for(j=1;j<=n;j++) s+=A[i][j]*B[j][k]; D[i][k]=s; } } } void gauss(complex<double>** a,int n,double eps,complex<double>* b){ int i,j,k,wm; complex<double> p,w; double max; w=1.0; for (i=1;i<n;i++){ max=abs(a[i][i]); wm=i; for(j=i+1;j<=n;j++) if(abs(a[j][i])>max){ max=abs(a[j][i]); wm=j; } if(wm>i) { for(k=i;k<=n+1;k++){ p=a[i][k]; a[i][k]=a[wm][k]; a[wm][k]=p; } w*=−1.0; } if (abs(a[i][i])<eps) w=0; if (w!=0.0) for(j=i+1;j<=n;j++){ p=complex<double>(a[j][i]/a[i][i]); for(k=n+1;k>i;k−−) a[j][k]−=p*a[i][k]; } w*=a[i][i]; } w*=a[n][n]; if(abs(w)<eps) w=0.0; b[0]=w; if(b[0]!=0.0) for(i=n;i>=1;i−−){ p=a[i][n+1]; for(j=i+1;j<=n;j++) p−=a[i][j]*b[j]; b[i]=complex<double>(p/a[i][i]); } } complex<double> det(complex<double>** a,int n,double eps){ int i,j,k,wm; complex<double> p,w; double max; w=1.0; for (i=1;i<n;i++){ max=abs(a[i][i]); wm=i; for(j=i+1;j<=n;j++) if(abs(a[j][i])>max){ max=abs(a[j][i]); wm=j; } if(wm>i) { for(k=i;k<=n+1;k++){ p=a[i][k]; a[i][k]=a[wm][k]; a[wm][k]=p; } w*=−1.0; } if (abs(a[i][i])<eps) w=0; if (w!=0.0) for(j=i+1;j<=n;j++){ p=complex<double>(a[j][i]/a[i][i]); for(k=n+1;k>i;k−−) a[j][k]−=p*a[i][k]; } w*=a[i][i]; } w*=a[n][n]; return w; } void swapcols(int n,int p,int q,complex<double>** a,complex<double>** b){ int i,j; complex<double> t; for(i=1;i<=n;i++) for(j=1;j<=n+1;j++) b[i][j]=a[i][j]; for(i=1;i<=n;i++){ t=b[i][p]; b[i][p]=b[i][q]; b[i][q]=t; } } void cramer(complex<double>** A,int n,double eps,complex<double>* X){ int i; complex<double>** B; B=new complex<double>*[n+2]; for(i=0;i<=n+1;i++) B[i]=new complex<double>[n+2]; for(i=1;i<=n;i++){ swapcols(n,i,n+1,A,B); X[i]=det(B,n,eps); } X[0]=det(A,n,eps); if(X[0]!=0.0) for(i=1;i<=n;i++) X[i]=complex<double>(X[i]/X[0]); for(i=0;i<=n+1;i++) delete[] B[i]; delete[] B; } void ludcmp(complex<double>**a,int n,int* indx,complex<double>&d) { int i,imax,j,k; complex<double> big,dum,sum,temp; complex<double>* vv; double tiny=1e−20; vv=new complex<double>[n+1]; d=1.0; for(i=1;i<=n;i++){ big=0.0; for(j=1;j<=n;j++) if(abs((temp=abs(a[i][j])))>abs(big)) big=temp; if(big==0.0) { d=0.0; return; } vv[i]=complex<double>(1.0/big); } for(j=1;j<=n;j++){ for(i=1;i<j;i++){ sum=a[i][j]; for(k=1;k<i;k++) sum−=a[i][k]*a[k][j]; a[i][j]=sum; } big=0.0; for(i=j;i<=n;i++){ sum=a[i][j]; for(k=1;k<j;k++) sum−=a[i][k]*a[k][j]; a[i][j]=sum; if(abs((dum=vv[i]*abs(sum)))>=abs(big)){ big=dum; imax=i; } } if(j!=imax){ for(k=1;k<=n;k++){ dum=a[imax][k]; a[imax][k]=a[j][k]; a[j][k]=dum; } d=−d; vv[imax]=vv[j]; } indx[j]=imax; if(a[j][j]==0.0) a[j][j]=tiny; if(j!=n){ dum=1.0/(a[j][j]); for(i=j+1;i<=n;i++) a[i][j]*=dum; } } delete[] vv; } void lubksb(complex<double>** a,int n,int*indx,complex<double> *b) { int i,ip,j,ii=0; complex<double> sum; for(i=1;i<=n;i++) { ip=indx[i]; sum=b[ip]; b[ip]=b[i]; if(ii) for(j=ii;j<=i−1;j++) sum−=a[i][j]*b[j]; else if(abs(sum)) ii=i; b[i]=sum; } for(i=n;i>=1;i−−){ sum=b[i]; for(j=i+1;j<=n;j++) sum−= a[i][j]*b[j]; b[i]=complex<double>(sum/a[i][i]); } } Spróbuj coś z tego wyciągnąć
7 sty 20:49
jc: To będzie działać tylko dla n=100. Ja bym używał tablic jednowymiarowych. Zamiast pow(−1,i+j) napisz raczej coś takiego 1−2*((i+j)%2) lub 1−2*(i+j)&1.
7 sty 20:49
Mariusz: #include<stdio.h> #include<stdlib.h> #include<conio.h> /* Obliczanie wyznacznika metodą rozwinięć Laplace */ double det(double**, int); int main(){ int i,j,n; double** a; char ch; do{ printf("Podaj n="); scanf("%d",&n); a=(double**)malloc((n+1)*sizeof(double)); for(i=0;i<n+1;i++) a[i]=(double*)malloc((n+1)*sizeof(double)); for(i=0;i<n;i++){ for(j=0;j<n;j++){ printf("A[%d][%d]=",i+1,j+1); scanf("%lf",&a[i][j]); } printf("\n"); } printf("det(A)=%lf\n",det(a,n)); free(a); ch=getch(); } while(ch!=27); return 0; } double det(double** a, int size) { int i, k, l, z = 1; double** b; double d = 0; b=(double**)malloc((size+1)*sizeof(double)); for(i=0;i<size+1;i++) b[i]=(double*)malloc((size+1)*sizeof(double)); if (size == 1) d = a[0][0]; else { // rozwiniecie Laplace'a względem pierwszego wiersza for (i = 0; i < size; i++) { // przepisywanie wierszy for (k = 0; k < size − 1; k++) { // przepisywanie kolumn for (l = 0; l < size − 1; l++) { // przepisanie komórki znajdującej się w tej // samej kolumnie lecz w wierszu poniżej if (l < i) b[k][l] = a[k + 1][l]; // przepisanie komórki znajdującej się // w następnej kolumnie i wierszu poniżej else b[k][l]=a[k + 1][l + 1]; } } // wywołanie rekurencyjne d = d + z * a[0][i] * det(b, size−1); // zmiana znaku z = −z; } } free(b); return d; } Masz tutaj wyznacznik z rozwinięcia Laplace Może się przydać
7 sty 20:55
Benny: Bo to ma działać dla n≤100. Czy ten zapis, który ja zastosowałem jest błędny? Co oznacza zapis 1−2*(i+j)&1?
7 sty 20:56
jc: a&b oznacza logiczne "i" wykonane na każdym bicie osobno 1010 & 1100 = 1000 n&1 = 0 dla liczb parzystych, 1 dla nieparzystych 1 = 0001 (trochę zer, a na końcu 1)
7 sty 21:06
Benny: Ok, dzięki.
7 sty 21:16