Einführung /Grundbegriffe

Werbung
3. Datentypen, Ausdrücke und Operatoren
­ Programm muß i.a. Daten zwischenspeichern
­ Speicherplatz muß bereitgestellt werden, der ansprechbar, reserviert ist
Ablegen & Wiederfinden
­ in höheren Programmiersprachen Arbeit mit bestimmten Speicherplätzen über Vergabe von Namen = Variable
3.1 Variable
im Programm definierter Name für einen (beim Programmlauf) zu
reservierenden Speicherplatz im Arbeitsspeicher für Werte eines bestimmten Typs
Arbeit mit Variablen (Zuweisungen von Werten, Berechnungen) bedeutet
Zugriff auf den zugehörigen Speicherplatz
Deklaration in C:
Beispiel: Variablentyp Variablenname;
int i; Deklaration der integer­Variablen mit Namen i
d.h. Bereitstellen von i.a. 4 Byte Speicherplatz (=32 bit)
im Arbeitsspeicher
i=3;
Speicherung des Wertes 3=2^0+2^1(≙ 11 binär)
auf dem reservierten Speicherplatz
1
000...
➘
...
...
i
...0011
Arbeitspeicher
­ in vielen höheren Programmiersprachen ist zur Reservierung eines Speicherplatzes, d.h. der Einführung einer neuen Variablen ein Variablentyp mit anzugeben
­ der Variablentyp sagt dem Compiler wieviel Speicherplatz benötigt wird und wie er zu strukturieren ist (zu interpretieren)
3.2 Elementare Datentypen
­ Es gibt drei qualitativ unterschiedliche Basistypen von Daten:
ganze Zahlen, reelle Zahlen und alphanumerische Zeichen
­ Die Basistypen werden i.a. in eine Reihe von Untertypen ( die sogenannten elementaren Typen) aufgesplittet.
­ Die Bezeichnungen der Typen ist sprachabhängig, z.B.
ganze Zahlen : int , long , short integer, longint, word INTEGER (in C) (in PASCAL)
(in FORTRAN)
reelle Zahlen : float, double
real, extended REAL, DOUBLE
(in C) (in PASCAL)
(in FORTRAN)
Zeichen : char
CHARACTER
(in C und in PASCAL)
(in FORTRAN)
(1) Integertypen in C:
int
short int
long int
kurz: short
kurz: long
Speicherbedarf:
­ Speicherplatz für int = Wortlänge des Rechners
­ heutzutage auf dem PC meist 4 Byte = 32 Bit
⇨ max. bzw. min. darstellbare Zahl:
32 Stellen = 32 Möglichkeiten für 0 oder 1 ⇨ 2^32 verschiedene Zahlen darstellbar
Sinnvolle Möglichkeiten:
(A) das erste Bit gleich 0 bedeutet positive Zahl
1 bedeutet negative Zahl
alle anderen Bits repräsentieren den Betrag der ganzen Zahl
Diese Darstellungsweise ist auf den ersten Blick sehr sympathisch, hat aber praktische Nachteile, besonders bei der Addition negativeR Zahlen.
(B) Deshalb:
Kodierung in sog. Zweierkomplementdarstellung
Für negative ganze Zahlen bedeutet das:
­ Die Bitfolge der zugehörigen betragsgleichen positiven Zahl wird logisch
negiert, d.h. aus jeder 0 wird eine 1 und aus jeder 1 wird eine 0. ­ Anschließend wird zu der so erhaltenen Zahl eine 1 addiert.
Beispiel betrachten hier einen max. Umfang von 4 Bit: < C Typ short ⇨bei 32 Bit ist der Bereich: ­231 bis 231­1 231 negative Zahlen, 0 und 231–1 positive Zahlen
Maximale Zahl = 231–1 ~ 2 Mio.
Unterschiede zwischen long int, int, short int sind compilerabhängig
(2) Gleitkomma­Typen Darstellung reeller Zahlen
Typen in C: float ... einfache Genauigkeit
double ... doppelte Genauigkeit
Was bedeutet einfach, was bedeutet doppelt genau?
Und was ist eigentlich eine Gleitkommazahl?
­ anderer Name: Maschinenzahl
Festkommadarstellung z.B. : 321.45 Gleitkommadarstellung : 3.2145*102 bzw. 0.32145*103
Prinzipielles Problem: Da nur beschränkte Anzahl an Bytes zur Darstellung zur Verfügung steht, ist in der
Regel eine genaue Darstellung nicht möglich. Irrationale Zahlen wie 2 oder die Eulersche Zahl e intern nie exakt darstellbar.
aber auch viele andere nicht.
­ interne Darstellung im Rechner:
x = (­1)v  0.m1 m2  mL 2p

 
Vorzeichen Mantisse
Basis + Exponent
mi ... sind 0 oder 1, m1 = 1
p ... ist der Exponent (selbst wieder intern binär gespeichert), m p  M (d.h. Beschränkt)
v ... ist 0 oder 1 d.h. das Komma wird immer an der selben Stelle plaziert.
Speicherplatz:
Für die Codierung im Computer ist IEEE­Standard üblich
● für Gleitkommazahl in einfacher Genauigkeit: 4Byte = 32 Bit
v
e7 ... e0
m2 ... ... m24
Vorzeichenbit Exponent Mantisse
m1 muß nicht gespeichert werden, da stets = 1
●
für Gleitkommazahl in doppelter Genauigkeit: 8Byte = 64 Bit
v
e10 ... ... e0
m2 ... ... ... ... ... m53
Vorzeichenbit Exponent Mantisse
Typ
Max. /pos. Min.
Rel. Rechengenauigkeit eps
float
~ 1038 / ~ 10­38
~ 0.610­7
double
~ 10308 / ~ 10­308
~ 1.110­16
z.B. MAXFLOAT ~ 2M , M = 27 = 128 2M = 2128 ~ 1038
⇨Mantisse bestimmt die Rechengenauigkeit
⇨Exponent bestimmt den Wertebereich
Grenzen der Maschinenzahlen:
Unterlauf (underflow):
|x| < eps  Rundung x=0 Überlauf (overflow)
|x| > MAX_Typ  compilerabhängige Reaktion
­ Abbruch + Fehlermeldung
­ falsches Ergebnis
­ x=INF oder x=NaN
Bei der Darstellung selbst einfachster Dezimalzahlen treten schon Rundungsfehler auf.
Zusätzlich ergeben sich beim Rechnen weitere Rundungsfehler:
Bei Addition zweier (positiver) Gleitkommazahlen werden folgende Einzelschritte ausgeführt:
1. Erkennen von Mantisse und Exponent beider Zahlen
2. Vergleichen der Exponenten
3. Angleichen der Exponenten
4. Anpassen der Mantisse der Zahl, deren Exponent bei der Exponentenanpassung verändert wurde
5. Addition der Mantissen, ggf. Änderung des gemeinsamen Exponenten (bei Überlauf der Mantisse)
6. Normalisierung des Ergebnisses (gleitendes Komma)
Beispiel: Die Eulersche Zahl e = 2.71828182846 ... ist Grenzwert der Zahlenfolge
a1 , a2 , a3 , .... an , ... mit an = (1 + 1/ n ) n Es gilt an < an+1 (Monotonie !) und an < e für alle natürlichen Zahlen n.
Folglich erhält man (mathematisch betrachtet) mit wachsendem n einen immer besseren Näherungswert für e .
(3) Textzeichentyp
char
reserviert (i.a.) 1 Byte = 8 Bit Speicherplatz für genau ein Zeichen
(Erinnerung: z.B. ASCII­Code stellt Zeichen auf 8 Bit dar)
ein erster abgeleiteter Variablentyp:
Zeichenkette
Aufeinanderfolge von Zeichen (z.B. Wörter)
dargestellt und gespeichert als Feld des Typs char
anderer Name: string
Deklaration: char stringname[n];
dabei ist n die maximale Anzahl Zeichen, d.h. die Feldlänge
­ durch die Deklaration wird ein Block von n Byte Speicherplatz im
Arbeitspeicher reserviert. ­ Achtung! Der Name stringname enthält dabei die Speicheradresse, an der
die Zeichenkette im Arbeitspeicher beginnt (stringname ist ein sog. Zeiger)
­ Zugriff auf die Komponenten, also die einzelnen Zeichen durch
stringname[i]
wobei der Index i das i­1 . Zeichen der Zeichenkette bezeichnet, da in C die Numerierung bei 0 beginnt!
z.B. char str[5]="INFO";
str
➘
I
N
F
O
\0
1012 1013 1014 1015 1016 1017 ...


 
str[0] str[1] str[2] str[3] Endezeichen
str enthält die Adresse 1015
str[0] = 'I', str[1]='N' , ...
­ gespeichert wird natürlich jedes Zeichen in seiner Binärdarstellung!
­ es muß stets ein Byte Platz für das Endezeichen eingerechnet werden,
sonst kann es zu Problemen führen Erreichen des Endezeichens kann z.B. in einer Schleifenanweisung durch
i=0;
while (str[i]!=0)
{
tue etwas
i=i+1;
}
abgefragt werden.
­ Achtung! Zuweisung eines ganzen Wortes nur in der Deklaration erlaubt
danach nur noch Zugriff auf Einzelkomponenten möglich
(4) leerer Typ
void
sinnvoll z.B. Für Funktionen ohne Ergebniswert (sog. Prozeduren oder Subroutinen)
aus diesen Grundtypen lassen sich dann beliebig komplexere Typen selbstdefinieren
(dazu mehr in der 4. Vorlesung)
3.3 Ausdrücke und Operatoren
Ein Ausdruck ist eine Aneinanderreihung von Zahlen, Strings und Operatoren, die sich zu einem Wert auflösen lassen, sprich: eine mehr oder weniger komplexe Rechenvorschrift
⇨Ausdrücke können über Operatoren miteinander verknüpft werden ⇨Ausdrücke können Variablen zugewiesen werden
Operatoren: es gibt grundsätzlich unäre, binäre und terniäre Operatoren
z.B.:
(1) unäre Operatoren: (in C) Inkrementoperator ++ausdruck
ausdruck++ Dekrementoperator ­­ausdruck
ausdruck­­
(2) binäre Operatoren: arithmetische Grundoperationen + , ­ , * , / (in allen Programmiersprachen)
(3) terniäre Operatoren: eher selten
in C z.B. Ausdruck1 ? Ausdruck2 : Ausdruck3
ist Ausdruck 1 wahr so berechne Audruck2 sonst berechne Ausdruck3
Zuweisung: (binärer Operator)
Variablenname = Ausdruck
­ eine Zuweisung ist selbst wieder ein Ausdruck ­ die Zuweisung hat den Wert, der der Variablen zugewiesen wird
Vergleiche und logische Operatoren
Vergleiche
Symbolik fürVergleiche in Programmiersprachen ähnlich der aus
der Mathematik bekannten: < , > ≤ ... <=
≥ ...
>=
= ... ==
doppeltes Gleichheitszeichen, da '=' der Zuweisung entspricht
allgemein ist die Syntax:
Ausdruck Vergleichsoperator Ausdruck
­ liefert wieder einen Ausdruck
­ dieser Ausdruck hat einen int­Wert, und zwar 0 , falls der Vergleich nicht zutrifft
1, falls der Vergleich zutrifft
Logische Operatoren
Aussagenlogisches UND
Symbolik:
&&
.and. &
ODER
||
.or.
|
VERNEINUNG
!
.not.
~
(in C)
(in FORTRAN)
(in MATLAB)
Ausdruck logischer Operator Ausdruck
­ liefert wieder einen Ausdruck
­ dieser Ausdruck hat einen int­Wert, und zwar 0 , falls der Gesamtausdruck wahr
1, falls der Gesamtausdruck falsch ist Anweisungen ­ sind in der jeweiligen Programmiersprache erlaubte Ausdrücke, die zeilenweise in den
Programmen geschrieben werden (oder durch entsprechende Zeichen voneinander
abgegrenzt, z.B. ein Komma in FORTRAN oder in MATLAB)
­ möglicherweise prinzipiell durch ein Zeichen abgeschlossen werden in C: Ausdruck ;
Priorität von Operatoren
(von höchster zu niedrigster Priorität)
Symbol Name/Bedeutung Assoziativität
----------------------------------------------------------------++
Erhöhung nach Auswertung
von links nach rechts
-Erniedrigung nach Auswertung
( )
Funktionsaufruf
[ ]
Arrayelement
->
Zeiger auf Strukturfeld
.
Felder einer Struktur oder Union
----------------------------------------------------------------++
Erhöhung vor Auswertung
von rechts nach links
-Erniedrigung vor Auswertung
!
logisches NOT
unäres Minus
+
unäres Plus
&
Adresse von
*
Dereferenzierung
sizeof Größe in Bytes
(type) Typumwandlung (cast)
----------------------------------------------------------------*
/
Multiplikation
Division
von links nach rechts
%
Divisionsrest (modulo)
----------------------------------------------------------------+
Addition
von links nach rechts
Subtraktion
----------------------------------------------------------------<
kleiner als
von links nach rechts
<=
kleiner oder gleich
>
größer als
>=
größer oder gleich
----------------------------------------------------------------==
gleich
von links nach rechts
!=
ungleich
----------------------------------------------------------------&&
logisches AND
von links nach rechts
----------------------------------------------------------------||
logisches OR
von links nach rechts
----------------------------------------------------------------? :
Bedingung
von rechts nach links
----------------------------------------------------------------=
Zuweisung
von rechts nach links
*=
zusammengesetzte Zuweisung
/=
%=
+=
-=
<<=
>>=
&=
^=
|=
----------------------------------------------------------------,
Komma-Operator
von links nach rechts
-----------------------------------------------------------------
Typumwandlung
nötig, falls in einer Operation Operanden verschiedenen Typs beteiligt sind
● implizite Typumwandlung: durch den Compiler
z.B. int i=1, k=3;
float x;
x = i*k; int*int liefert int, in der Zuweisung Umwandlung intfloat
●
explizite Typumwandlung: durch einen cast­Operator z.B. float y = 6.78;
i = 3 + (int) y;
Herunterladen