Testklausur zur Vorlesung Angewandte Informatik

Werbung
Testklausur zur Vorlesung
Angewandte Informatik
Prof. Dr. Nikolaus Wulff
18. Januar 2006
Diese Klausur besteht aus fünf Aufgaben, von denen Sie drei bearbeiten
und lösen müssen, d.h. maximal drei richtig gelöste Aufgaben entsprechen 100% der Gesamtpunktzahl.
1. Schauen Sie sich daher die Aufgaben zu nächst in Ruhe an und
wählen Sie dann die Aufgaben, die Ihnen am leichtesten erscheinen. Sofern Sie mehr als drei Lösungen abgeben, werden die drei
schlechtesten Aufgaben bewertet.
2. Schreiben Sie auf jedes Lösungsblatt Ihre Matrikelnummer und zu
welcher Aufgabe es gehört. Nummerieren Sie die Lösungsblätter
durch.
3. Schreiben Sie leserlich, Hieroglyphen werden nicht gewertet.
4. Kommentieren Sie ihre Programmlistings, so dass klar ist, was Sie
damit bezwecken.
5. Für diese Klausur sind keine Hilfsmittel zugelassen.
Viel Erfolg!
1
1
Zahlen Ring
√
√
Die Menge Z[ 2] := a + 2 · b | ∀ a, b ∈ Z wird mit den beiden binären
√
√
√
Operationen ⊕ und ⊗ : Z[ 2] × Z[ 2] → Z[ 2]
√
√
√
(a + 2 · b) ⊕ (c + 2 · d) 7→ (a + c) + 2 · (b + d)
(1)
√
√
√
(a + 2 · b) ⊗ (c + 2 · d) 7→ (ac + 2bd) + 2 · (ad + bc)
(2)
√
zu einem Ring (Z[ 2], ⊕, ⊗). Modellieren Sie diesen Datentyp in C, in einer
Datei Ring.h:
/** Ring.h */
#ifndef __RING_H
#define __RING_H
typedef struct ring_struct Ring;
struct ring_struct {
/* fields missing
...
*/
};
/* methods missing
...
*/
#endif /* __RING_H defined */
mit geeignet ausgeprägten Feldern und Methoden√für die Operationen +, −
und ∗. Achtung Division ist für einen Ring über Z[ 2] nicht definiert. Geben
Sie die Implementierung der Operationen + und ∗ aus der Datei Ring.c an:
/** Ring.c */
#include "Ring.h"
Ring add(Ring p, Ring q) {
...
}
Tip:
√
Sie benötigen die 2-Funktion nicht zur Implementierung. Sie hat eine analoge Bedeutung, wie die Imaginäre Zahl i bei den komplexen
Zahlen und
√
wird nicht explizit ausgewertet. Die Elemente z ∈ Z[ 2] sind also Tupel
(a, b) mit a, b ∈ Z, die lediglich mit etwas ”anderen Verknüpfungen” für
+, − und ∗ versehen sind.
2
2
Ermittlung der Nullstelle einer reelen Funktion
Entwickeln Sie einen Algorithmus zur Bestimmung der Nullstelle einer reelwertigen, stetigen Funktion f (x) nach dem Newtonverfahren. Hierzu wird
eine Folge (xn ) von Punkten rekursiv nach der Vorschrift
xn+1 := xn −
f (xn )
, ∀n ∈ N
f 0 (xn )
(3)
gebildet. Diese Vorschrift macht natürlich nur für f 0 (x) 6= 0 im betrachteten Bereich Sinn, wovon Sie hier der Einfachheit halber stillschweigend von
ausgehen dürfen. Ihre Aufgabe ist es zu der C Header Datei
/**
Newton.h
*/
#ifndef __NEWTON_H
#define __NEWTON_H
/* define a function pointer as type
*/
typedef double (*Function)(double x);
/**
* newton returns double x with f(x)=0
*/
double newton(
Function F,
/* function to use
*/
Function dF,
/* first derivative of F
*/
double x0,
/* x_0 iteration start point */
double epsilon); /* precision of x_n
*/
#endif
eine geeignete Implementierung zu entwickeln. Die Routine newton berechnet unter Ausnutzung von Formel (3) eine Approximation der Nullstelle
x0 bei gegebenen Funktionen f (x) ≡ F (x) und f 0 (x) ≡ dF (x), zu einem vorgegebenem Approximationsstartwert x0 und einer Fehlerschranke
. Sehen Sie eine maximale Anzahl an Iterationsschritten vor, die sie per
#define MAX_STEPS xx definieren, so dass der Algorithmus abbricht falls
keine Konvergenz eintritt. Überlegen Sie sich, wie sie eine geeignete Abbruchbedingung überprüfen. Verwenden Sie zur Auswertung von Formel (3)
eine geeignete Unterroutine innerhalb der Methode newton, so dass der Code
modular aufgebaut ist.
3
3
Stapel
Modellieren Sie den Datentypen eines Stapels (engl. Stack) als einfach verkettete Liste, nach dem LIFO Prinzip (last in first out), wie in Abbildung 1
dargestellt, mit einem möglichen Top Element, einmal als C struct und einmal als Java Klasse. Geben Sie hierzu die C Header-Datei stack.h und die
Java Klasse Stack.java an. Für C reicht eine ausformulierte Header Datei,
mit allen vorgesehenen typedefs. Sollte allerding Java nicht die Sprache Ihrer Wahl sein, muss stattdessen eine entsprechende Implementierungsdatei
stack.c abgegeben werden.
0,1
Stack
Object
Q
Q push(Object o)
cellar
pop(): Object
size(): int
Abbildung 1: UML Diagramm eines Stacks.
Eine solcher Stapel wird intern als Liste rekursiv definiert, indem das erste
Stack Objekt eine Referenz auf das folgende Stack Stapel Objekt der letzten push Operation enthält, Abbildung 2. In der pop Operation wird dieses
oberste Keller Stack Element entfernt, nachdem vorher die Keller Referenz
auf das dann aktuelle oberste Stack Element umgehängt wurde.
Entnehmen Sie die zu implementierenden Methoden dem UML Diagramm 1.
In der C Implementierung modellieren Sie einen generischen Pointer auf ein
Objekt als void*. Bedenken Sie, dass in der C Implementierung die Signatur
der Methoden mehr Parameter erfordert als in Java.
head
t
t
?
obj
cellar
-
t
t
cellar
-
?
obj
t
t
cellar
-
?
obj
Abbildung 2: Sich referenzierende Stack Objekte.
4
d
d
/**
Stack.h
*/
#ifndef __STACK_H
#define __STACK_H
typedef void* Object;
typedef struct ...
struct stack_struct {
/* fields missing
...
*/
};
/* methods missing
...
*/
#endif
/**
* Stack.java
*/
public class Stack {
// attributes missing
// functions missing
} // class Stack
Stack head = ...
int objs[] = {1,2,3,4,5};
int i, n = sizeof(objs)/sizeof(objs[0]);
for (i=0; i<n; i++) {
push(head,objs+i);
}
printf("stack size: %d\n",size(head));
for (i=0; i<n; i++) {
Object obj = pop(head);
int o = *(int *) obj;
printf("%d obj: %d \n",i, o );
}
Das Beispiel verdeutlicht die Verwendung der C Stackimplementation. Der
Aufrufende erhält nur eine Referenz auf das Stack head Element, ohne die
weiteren Stackinstanzen zu verwenden oder zu kennen.
5
4
Interpolation von Messwerten
Gegenen sei eine Folge (yk ) von n+1 Messewerten, mit den Stützstellen (xk ),
wobei der Laufindex k von k = 0, ...n läuft. Gesucht ist der interpolierte Wert
y an einer beliebigen Stelle x aus dem Interval [x0 , xn ]. Entwickeln Sie hierzu
die Methode interpolate(x), die zu gegebenen Messwerten die Interpolation
an der Stelle x liefert. Nach der Methode von Aitken und Neville wird hierzu
rekursiv ein Satz von Polynomen Pj,k (x) definiert, mit der Vorschrift
P0,k (x) = yk für 0 ≤ k ≤ n
(x − xk−j )Pj−1,k (x) − (x − xk )Pj−1,k−1 (x)
,1 ≤ j ≤ k ≤ n
Pj,k (x) =
xk − xk−j
Das Polynom Pn,n (x) ≡ interpolate(x) liefert dann genau den gesuchten
interpolierenden Rückgabewert. Die Methode interpolate(x) wird nach der
Initialisierung der Interpolator Klasse mit den Stützstellen (xk ) und den
Messpunkten (yk ) aufgerufen. Die Implementierungsdatei Interpolator.java
verwendet hierzu intern das Polynom Pn,n (x) zum Berechnen des gesuchten
y Wertes.
/**
Interpolator.java
*/
public class Interpolator {
private double[] xv, yv;
public Interpolator(double[] x, double[] y) {
this.xv = x;
this.yv = y;
}
public double interpolate(double x) {
int n= xv.length - 1;
return polynom(n,n,x);
}
private double polynom(int j, int k, double x) {
// implementation still missing ...
return ???
}
}
Geben Sie die Implementierung der Methode polynom(j,k,x) an und zeichnen
Sie den Aufrufgraph für den Aufruf von P2,2 (x).
6
5
Gerichteter Graph
Gegeben sei der gerichtete Graph G = (V, E) mit V = {A, B, C, D, E} und
der Relation E = {(A, B), (A, D), (B, E), (C, A), (C, E), (D, E)}.
• Zeichnen Sie den Graph G.
• Wie lautet die Adjazenzmatrix AG ?
• Zeichnen Sie den Graph der Transitiven Hülle von G.
• Wie lautet die Adjazenzmatrix RG der Transitiven Hülle?
• Wie lautet die Relation E(RG ) der Transitiven Hülle?
• Enthält der Graph Schleifen?
Begründen Sie Ihre Ergebnisse/Aussagen.
7
Herunterladen