Vorlesung 11 Flashcards
Mathematische Funktionen
● Header-Datei math.h
● Funktionsübersicht
* double sin(double x): Sinus von x
* double cos(double x): Cosinus von x
* double tan(double x): Tangens von x
* double asin(double x): Arcussinus von x im Bereich [-π / 2, π / 2], x ∈ [-1,1]
* double acos(double x): Arcuscosinus von x im Bereich [0, π], x ∈ [-1,1]
* double atan(double x): Arcustangens von x
* double atan2(double y, double x): Arcustangens von y/x
* double sinh(double x): Sinus Hyperbolicus von x
* double cosh(double x): Cosinus Hyperbolicus von x
* double tanh(double x): Tangens Hyperbolicus von x
* double exp(double x): Exponentialfunktion ex
* double log(double x): natürlicher Logarithmus ln x, x > 0
* double log10(double x): Logarithmus zur Basis 10, log10 x, x > 0
* double pow(double x, double y): Potenz xy,
nan („not a number“), wenn x = 0 und y ≤ 0, oder x < 0 und y nicht ganzzahlig
* double sqrt(double x): Wurzel von x,
nan („not a number“), wenn x < 0
* double fabs(double x): Betrag von x. (Hinweis: int abs(int x) in stdlib.h)
* double ceil(double x): aufrunden auf die nächste ganze Zahl, ⌈x⌉
* double floor(double x): abrunden auf die nächste ganze Zahl, ⌊x⌋
* double ldexp(double x, int n): x·2n
* double frexp(double x, int *exp): zerlegt x in normalisierte Mantisse im
Bereich [1/2, 1), (Rückgabewert), und eine Potenz von 2, (in *exp abgelegt),
beide 0, wenn x=0
* double modf(double x, double *ip): zerlegt x in ganzzahligen Teil (in *ip
abgelegt) und den Rest (Rückgabewert), beide haben gleiches
Vorzeichen wie x
* double fmod(double x, double y): Gleitpunktrest von x/y, Vorzeichen wie x
Der Präprozessor
Wichtigste Aufgaben des Präprozessors
* Einbinden externer Dateien (#include)
* Textuelles Ersetzen symbolischer
Konstanten und Makros (#define)
* Bedingte Kompilierung (#ifdef)
● Präprozessoranweisungen beginnen mit #
● Anweisungen über mehr als eine Zeile: Jede Zeile, die fortgesetzt werden
soll, muss mit \ abgeschlossen werden
Einbinden externer Dateien
Mit #include wird eine Datei an der angegebenen Stelle in den Quelltext
eingefügt.
● Syntax
* #include <datei>: Sucht die Datei im Standard-Include-Verzeichnis
* #include "datei": Sucht die Datei im aktuellen Verzeichnis
● Anwendung
* Einbinden der Standard-Header-Dateien
* Einbinden eigener Header-Dateien</datei>
Makrodefinitionen
● Makrodefinition mit #define
● Makrosubstitution: der Bezeichner des Makros wird im folgenden durch die
definierte Zeichenkette ausgetauscht.
● Syntax:
* #define name [(Parameterliste)] [wert]
* Makros mit/ohne Parameter und mit/ohne Ersetzungstext möglich
Parametrisierte Makros
define MAX(x,y) (((x)>=(y))?(x):(y))
Zwischenstufe“ zur Funktion
…
z = MAX(3.2, sin(y));
{ \
int h; \
h = x; x = y; y = h; \
}
…
int i = 3, j = 5;
TAUSCHE_INT(i, j)
Bedingte Übersetzung
● Übersetzung abhängig davon, ob ein Makro definiert ist oder nicht
(Variante 1).
● Syntax:
– #ifdef Bezeichner1 oder #ifndef Bezeichner1
…
[#else
…
]
#endif
(Variante 2)
● Syntax:
– #if defined(Bezeichner1)
…
– [#elif defined(Bezeichner2)]
…
]
[#else
…
]
#endif
Bedingte Übersetzung
beispiel
define DEUTSCH
int main()
{
#if defined(DEUTSCH)
printf(“Hallo Welt!\n”);
#elif defined(ENGLISH)
printf(“Hello World!\n”);
#else
#error unbekannte Sprache
#endif
return 0;
}
wird zu
int main()
{
printf(“Hallo Welt!\n”);
return 0;
}
Zeiger auf Funktionen
- Im (von-Neumann-)Rechner stehen Daten und Programmcode
im selben Speicher. - Daher kann Programmcode als Daten und umgekehrt
aufgefasst werden. - Zeiger auf Funktionen zeigen auf den Anfang des Maschinencodes
einer Funktion. - Aufruf der referenzierten Funktion über den Funktionszeiger.
- Syntax: Datentyp (*Name)(<Parameterliste>);</Parameterliste>
- Deklariert Zeiger auf Funktion mit Parameterliste und
Rückgabewert Datentyp. - Wichtig: Funktionsname klammern, sonst würde eine Funktion mit
Rückgabetyp Zeiger definiert.
● Zuweisung mittels = und Name einer bekannten Funktion
f = quadrat;
Direktes Aufrufen der Funktion über Zeiger und Funktionsaufrufoperator ()
y = f(1.2);
Alternative: y = (*f)(1.2);
● Vorsicht: Funktionsparameter werden bei der Übersetzung nicht geprüft
(Flexibilität und Risiko zugleich).
● Zeiger auf Funktionen können auch als Funktionsparameter
verwendet werden.
2 Beispiele: Funktionszeiger
include <stdio.h></stdio.h>
/* erzeugt eine Wertetabelle für eine (fast) beliebige Funktion /
void wertetabelle(double min, double max,
double step, double (func)(double x))
{
double x;
printf(“ x | f(x) \n”);
printf(“——-+———-\n”);
for(x = min; x <= max; x += step)
{
printf(“%6g | %6g\n”, x, func(x));
}
}
double quadrat(double x)
{
return xx;
}
double polynom(double x)
{
return xx-3*x+2;
}
int main()
{
wertetabelle(-3, 3, 0.5, quadrat);
printf(“\n”);
wertetabelle(-3, 3, 0.5, polynom);
return 0;
}
Wie sucht man ein Element in einem beliebigen Array?
int* sucheElement(int* array, int anzahl, int element) {
for(int i = 0; i < anzahl; i++) {
if(element == array[i]) {
return &array[i]; // array + i
}
}
return NULL;
}
Sequentielle Suche
● Sequentielle Suche
* Algorithmus: Durchsuche die Folge von vorne bis hinten
* Maximal werden n Suchschritte bei einer Folge der Länge n benötigt
* Funktioniert auch bei unsortierten Folgen
Suche in sortierten Folgen
● Jetzt: Suche in einer sortierten Folge einen bestimmten Eintrag
● Beispiel: Ist ein bestimmter Name in der Folge (Alfons, Beate, Ines,
Klaus, Michael, Nadine, Peter, Ruth, Sabine, Sebastian, Tom)
enthalten?
Binäre Suche bei sortierten Folgen
- Algorithmus:
- Beginne in der Mitte des Feldes
- Wenn das zu testende Element dem Suchelement entspricht: fertig
- Ist das getestete Element kleiner als das Suchelement, muss die Suche rechts
fortgesetzt werden, sonst links - Fahre auf diese Weise in der Mitte der rechten bzw. linken Hälfte fort, solange,
bis das Element gefunden wurde oder feststeht, dass das Element nicht in der
Liste sein kann - Funktioniert nur bei sortierten Folgen
Bibliotheksfunktion zur Binären Suche
Bibliotheksfunktion zur binären Suche
void *bsearch(
const void *key,
const void base,
size_t n,
size_t size,
int (cmp)(const void *a, const void *b)
)
key = Suchwert
* base = das Feld, in dem gesucht werden soll (muss aufsteigend sortiert sein)
* n = Anzahl Elemente im Feld
* size = Größe eines Feldelements
* cmp = Zeiger auf eine Funktion, die den ersten Parameter (a) mit dem zweiten Parameter (b)
vergleicht und einen Wert < 0 zurückgibt, wenn a vor b in der Ordnung folgt, > 0, wenn
a nach b folgt und 0, wenn das Objekt gefunden wurde.
* Rückgabewert ist Zeiger auf das gefundene Element, oder NULL, wenn Element nicht gefunden wurde
Erläuterungen zu bsearch
- Die Funktion bsearch implementiert das allgemeine Vorgehen der binären Suche. Der
konkrete Inhalt des Arrays ist der Funktion „egal“. - Funktion ist unabhängig vom konkreten Datentyp, der im Array gespeichert ist:
- lediglich die Größe eines Elements muss angegeben werden, damit die Speicherzellen von
den Funktionen korrekt adressiert werden können - die Anzahl der Elemente muss übergeben werden, damit die Funktionen wissen, wie groß
das Feld ist
● Im Algorithmus ist es erforderlich, zwei Elemente zu vergleichen und zu
entscheiden, welches Element in der gesuchten Ordnung vor dem
anderen steht.
* dieser Teil ist als einziger nicht unabhängig vom Datentyp und kann daher nicht Teil der
allgemeinen Funktionen sein.
* stattdessen muss der Benutzer von bsearch selbst eine Funktion schreiben, die den
Vergleich vornimmt. Die Funktion wird als Parameter an bsearch übergeben.
* Notwendige Vereinbarung: Rückgabewert der selbstzuschreibenden Vergleichsfunktion
ist < 0, wenn Element 1 vor Element 2 kommt, > 0, wenn Element 1 nach Element 2
kommt und = 0, wenn sie gleich sind (vgl. strcmp).
* die beiden Parameter werden (um allgemein definiert sein zu können) als Zeiger auf
void (void*) übergeben und müssen zunächst in den eigentlichen Typ gewandelt
werden.
* bsearch ruft dann diese Funktion mit jeweils zwei Parametern aus dem Feld auf und
verfährt dann weiter gemäß dem entsprechenden Algorithmus.