Algorithmen und Programmierung II
Übungsblatt 2 - Musterlösung
Aufgabe 1
a)
static float ln2a(int n) {
float result = 0;
for (int i = 1; i <= n; i++)
result += (i % 2 == 0) ? -1.f/i : 1.f/i;
return result;
}
b)
static float ln2b(int n) {
float sum_pos = 0, sum_neg = 0;
for (int i = 1; i <= n; i++) {
if (i % 2 == 0)
sum_neg += 1.f/i;
else
sum_pos += 1.f/i;
}
return sum_pos - sum_neg;
}
c)
Der von ln2b berechnete
Näherungswert ist minimal besser als der von ln2a. Dies überrascht, da
der unter a) aufsummierte Werte etwas kleiner ist, als die beiden unter
b) separat berechneten Werte. Es werden zunehmend kleine Glieder zur
Teilsumme addiert, so dass deren Auslöschung droht. Bei der
Addition eines weiteren
Gliedes unter a) sollten geringfügig weniger Rundungsfehler
entstehen, als unter b).
Aufgabe 2
a)
Diagramm
Abkürzungen im Syntaxdiagramm:
AE
|
AssignmentExpression |
|
Li
|
Literal |
| AOp |
AssignmentOperator |
|
Pr
|
Primary |
| BE |
BinaryExpression |
|
RepSt
|
RepetitiveStatement |
| BOp |
BinaryOperator |
|
St
|
Statement |
| CompSt |
CompositeStatement |
|
StE
|
StatementExpression |
| DoSt |
DoStatement |
|
UE
|
UnaryExpression |
| E |
Expression |
|
V
|
Variable |
| ESt |
ExpressionStatement |
|
WhileSt
|
WhileStatement |
| Id |
Identifier |
|
|
|
b)
a=0, b > 0
|
Der Algorithmus terminiert
nicht, weil die Abbruchbedingung für die erste while-Schleife nie
erreicht wird. Es wird wiederholt 0 von b abgezogen, b wird nie kleiner
als a.
|
a > 0, b = 0
|
Die zweite while-Schleife
terminiert nicht, analog zum ersten Fall.
|
a = 0, b = 0
|
Der Algorithmus terminiert mit
dem Ergebnis 0. Dies ist zwar nach Definition kein Teiler, aber bei
dieser Eingabe vertretbar.
|
a < 0 und/oder b < 0
|
Der Algorithmus terminiert bei
einigen Parameter-Kombinationen mit einem falschen Ergebnis (negative
Zahl mit großem Betrag), bei anderen nie. Durch das negative
Vorzeichen wird der Betrag der einen Zahl wiederholt zur anderen
addiert. Durch den immer größer werdenden Wert kommt es
irgendwann zum Überlauf und je nach Parameter-Kombination kann
irgendwann "durch Zufall" die Abbruchbedingung der Schleife erreicht
werden.
|
Aufgabe 3
static void perfect() {
for (int n = 6; ; n++) {
int summe = 0;
for (int teiler = 1; teiler <= n/2; teiler++) {
if (n % teiler == 0)
summe += teiler;
}
if (n == summe)
System.out.println(n);
}
}