Ein Beispiel mit dem Bandbreitentupel (3,4):
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Aufgabe
Schreiben Sie ein Fortran95-Programm, welches das Bandbreitentupel (p,q) einer quadratischen Matrix ermittelt! Definieren Sie hierzu in einem Fortran 95-Modul eine ganzzahlige Funktion untere_bandbreite, welche die Bandbreite p einer als Argument übergebenen quadratischen reellen Matrix unbekannter Größe bestimmt. Hierfür sollen sukzessive die Diagonalen von links unten beginnend nach dem ersten Nichtnullelement abgesucht werden. Beachten Sie den Sonderfall der Nullmatrix!
Lösung
Es wird erst ein Feld unbekannter Größe definiert und mit dem Attribut Allocatable versehen. Damit kann man die Ausdehnung (Dimension) im Hauptprogramm nachträglich angeben z.B. nachdem man vom Benutzer die gewünschte Größe eingelesen hat.
Die Matrix wird dann Zeilenweise eingelesen. Dies wird durch die in Fortran 95 bestehende Teilfeldnotation erheblich vereinfacht: matrix(i,:) bedeutet alle Spalten der i-ten Zeile, also die komplette Zeile auswählen. Man kann nun in dieses Teilfeld schreiben oder auch ein Teilfeld auslesen. Schreibt man READ(*,*) matrix(i,:) erwartet das Programm die Eingabe aller Werte, die in das Teilfeld gespeichert werden sollen, durch Leerzeichen getrennt. Somit kann man eine Zeile komplett mit der Tastatur eingeben und muss nicht jedes Element einzeln abfragen.
Die Funktion untere_bandbreite wird dann in einem Modul definiert und gibt die untere Bandbreite (wie der Name schon sagt) zurück. Wenn man die obere Bandbreite bestimmen will, muss man nicht extra eine neue Funktion schreiben, sondern kann die bestehende auf die transponierte Matrix (mittels der vordefinierten Funktion transpose(matrix)) anwenden und erhält so das gewünschte Resultat.
Nun zum Quelltext des Hauptprogramms:
fortran Code
- PROGRAM bandmatrizen
- use bandbreite
- IMPLICIT NONE
- INTEGER :: n,i
- REAL,DIMENSION(:,:),ALLOCATABLE :: m
- write(*,*) 'n?'
- read(*,*) n
- allocate(m(n,n))
- write(*,*) 'Matrix zeilenweise eingeben:'
- do i=1,n
- read(*,*) m(i,:)
- end do
- write(*,*) 'p=',untere_bandbreite(m)
- write(*,*) 'q=',untere_bandbreite(transpose(m))
- deallocate(m)
- END PROGRAM bandmatrizen
fortran Code
- MODULE bandbreite
- IMPLICIT NONE
- PUBLIC
- CONTAINS
- FUNCTION untere_bandbreite(matrix)
- REAL,DIMENSION(:,:) :: matrix
- INTEGER :: untere_bandbreite,n,m,i,j
- LOGICAL :: notnull
- n = size(matrix,1)
- m = size(matrix,2)
- if(n /= m) then
- write(*,*) 'Es muss eine quadratische Matrix in die Funktion untere_bandbreite uebergeben werden'
- stop
- end if
- untere_bandbreite = n
- do i=n,1,-1
- notnull = .false.
- do j=0,n-1
- if(notnull .or. j+i>n) exit
- notnull = notnull .or. (matrix(i+j,j+1)/=0)
- end do
- if(notnull) then
- untere_bandbreite = i
- exit
- end if
- end do
- END FUNCTION untere_bandbreite
- END MODULE bandbreite