Gauß'sches Eliminationsverfahren in C aufbauend auf der LR Zerlegung



  • Hallo,

    ich möchte gerne das Gauß'sche Eliminationsverfahren in C programmieren.
    Mein Programm gibt auch keine Fehlermeldungen mehr aus, aber, wenn ich es starte, kommt die Fehlermeldung "Segmentation fault".
    (Das Programm baut auf http://www.c-plusplus.net/forum/289873 auf)

    Das ist mein Programm:

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    
    typedef double *PVector;
    typedef double **PMatrix;
    
    PVector TVector_Create(int n){
    	return (PVector) calloc(n, sizeof(double));
    }
    
    PMatrix TMatrix_Create(int m, int n){
    	PMatrix  A;
    	int i;
    	A = (PMatrix) malloc(m * sizeof(PVector));
    	for ( i=0; i<m; i=i+1 )
    		A[i] = TVector_Create(n);
    	return A;
    }
    
    PVector readVector(int n) {
    	int i;
    
    	PVector v = TVector_Create(n);
    
    	for(i = 0; i < n; i++){
    		printf("Geben Sie v %d ein\n", i+1);
    		scanf("%lf", &v[i]);
    		fflush(stdin);
    	}
    	return v;
    }
    
    PMatrix readMatrix(int m, int n) {
    	int i,j;
    
    	PMatrix A = TMatrix_Create(m, n);
    
    	for(i = 0; i < m; i++) {
    		for(j = 0; j < n; j++){
    			printf("Geben Sie A %d %d ein\n", i+1, j+1);
    			scanf("%lf", &A[i][j]);
    			fflush(stdin);
    		}
    	}
    	return A;
    }
    
    void writeVector(PVector v, int n) {
    	int i;
    
    	printf("(");
    	for(i = 0; i < n; i++) {
    		printf("%f,", v[i]);
    	}
    	printf(")\n");
    
    }
    
    void writeMatrix(PMatrix A,int m, int n) {
    	int i, j;
    
    	printf("(");
    	for(i = 0; i < n; i++) {
    		for(j = 0; j < m; j++) {
    			printf("%f,", A[i][j]);
    		}
    		printf(")\n");
    	}
    
    }
    
    //LR-Zerlegung
    
    void LRZerlegung(PMatrix A, int m, int n) {
    	int i, k, j;
    
    	for(i = 0; i < n; i++) {
    		// Bestimmen von R
    		for(j = i; j < m; j++) {
    			for(k = 0; k< i-1; k++){               
    				A[i][j]-= A[i][k] * A[k][j]; 
    			}
    		}
    		// Bestimmen von L
    		for(j = i+1; j<m; j++){
    			for (k = 0; k < i-1; k++){
    				A[j][i] -= A[j][k] * A[k][i];
    			}
    			A[j][i] /= A[i][i];
    		}
    	}
    }	
    
    int main(void){
    	int i, j, k, n, m;
    	PMatrix A;
    	PVector b;
    
    	//Eingabe der Dimension
    	printf("Geben Sie n an\n");
    	scanf("%d",&n);
    	fflush(stdin);
    	printf("Geben Sie m an\n");
    	scanf("%d",&m);
    	fflush(stdin);
    
    	//Eingabe: Matrix A
    	A = readMatrix(n, m);
    
    	//Eingabe: b
    	b = readVector(n);
    
    	//LR Zerlegung
    	LRZerlegung(A, m, n);
    
    	//Gauss-Elimination
    	for (k = 0; k<n-1; k++) {
    		if (A[k][k] == 0) {
    				 return 0;
    		}
    		else {
    				 for (i = k+1; i<n; i++){
    					A[i][k]= A[i][k]/A[k][k];
    					for (j=k+1; j<m; j++){
    						A[i][j]=A[i][j] - A[k][j]* A[i][k];
    						b[i]= b[i] - b[k]*A[i][k];
    					}
    				 }
    		}
    
    	}
    
    	//Linksdreieckssystem Ly = b lösen durch Vorwärtseinsetzen
    	b[0]= b[0]/A[0][0];
    	for (i=1; i<n; i++) {
    		for (j = 0; j<i-1; j++) {
    			b[i]=b[i]-A[i][j]*b[j];
    		}
    	}
    
    	//Rechtsdreieckssystem Rx = y lösen durch Rückwärtseinsetzen.
    	b[n]= b[n]/A[n][n];
    	for (i=n-1; i>=0; i--) {
    		for (j = i+1; j<m; j++) {
    			b[i]=b[i]-A[i][j]*b[j];
    			b[i]= b[i]/A[i][i];
    		}
    	}
    
    	writeVector(b, n);
    	return 0;
    }
    

    Kann mir da jemand weiter helfen?
    Vielen Dank!


  • Mod

    1. Arrays gehen immer noch bei 0 los! Zähl mal nach, welchen Index dann das letzte Element hat.
    2. Lern mal, einen Debugger zu benutzen. Das ist Grundwissen für die Programmierung und damit findet man solche Fehler sofort!
    3. fflush(stdin) löst undefiniertes Verhalten aus, außer auf einem gewissen Compiler von Microsoft.
    4. iostream? WTF?



  • Okay, das letzte Element hat nicht den Index n sondern n-1.
    Ich hab jetzt alle fflush(stdin) auskommentiert.
    #include <iostream> wurde automatisch hingeschrieben. Habe ich jetzt auch gelöscht.
    Das Programm rechnet jetzt zwar, aber es liefert leider nicht das richtige Erbenis 😞



  • Ich hab jetzt noch mal die Matrix A ausgeben lassen.
    Die wird richtig berechnet.
    Der Vektor beim Vorwärtseinsetzen ist leider schon falsch.
    Ich probiere mal den Fehler zu finden.



  • Das Programm läuft jetzt.
    Der fertige Code ist:

    int main(void){
    	int i, j, k, n, m;
    	PMatrix A;
    	PVector b;
    
    	//Eingabe der Dimension
    	printf("Geben Sie n an\n");
    	scanf("%d",&n);
    	//fflush(stdin);
    	printf("Geben Sie m an\n");
    	scanf("%d",&m);
    	//fflush(stdin);
    
    	//Eingabe: Matrix A
    	A = readMatrix(n, m);
    
    	//Eingabe: b
    	b = readVector(n);
    
    	//LR Zerlegung
    	//LRZerlegung(A, m, n);
    
    	//Gauss-Elimination
    	for (k = 0; k<n; k++) {
    		if (A[k][k] == 0) {
    				 return 0;
    		}
    		else {
    				 for (i = k+1; i<n; i++){
    					A[i][k]= A[i][k]/A[k][k];
    					for (j=k+1; j<m; j++){
    						A[i][j]=A[i][j] - A[k][j]* A[i][k];
    					}
    					 b[i]= b[i] - b[k]*A[i][k];
    				 }
    		}
    	}
    
    	//Linksdreieckssystem Ly = b lösen durch Vorwärtseinsetzen
    	//b[0]= b[0]/A[0][0];
    	//for (i=1; i<n; i++) {
    	//	for (j = 0; j<i-1; j++) {
    	//		b[i]=b[i]-A[i][j]*b[j];
    	//	}
    	//}
    
    	//Rechtsdreieckssystem Rx = y lösen durch Rückwärtseinsetzen.
    	b[n-1]= b[n-1]/A[n-1][n-1];
    	for (i=n-2; i>=0; i--) {
    		for (j = i+1; j<m; j++) {
    			b[i]=b[i]-A[i][j]*b[j];
    		}
    		b[i]= b[i]/A[i][i];
    	}
    
    	writeVector(b, n);
    	writeMatrix(A, m, n);
    	return 0;
    }
    

    Das Problem war, dass das Vorwärtseinsetzen schon in der Gauss-Elimination gemacht wurde und ich ein paar mal die Klammern für die for-Schleifen zu spät gesetzt hab, usw.

    Vielen Dank für die Hilfe!


Anmelden zum Antworten