Datentypen - Kekziie/Informatik-II-SS-2017 GitHub Wiki

Wortlängen und Speicherung von Variablen

Speicherplatz für eine Variable wird vor der Ausführung der ersten Anweisung reserviert

Wichtig: Der Compiler muss wissen, wie viel Speicherplatz reserviert werden muss!

Konsequenz: Jede Variable hat eine feste Anzahl von Speicherstellen, die durch den ihren Typ festgelegt wird.

Ganze Zahlen

Wertebereich für ganze Zahlen

  • byte [-128 ... 127]
  • short [-32768 ... 32767]
  • int [-2.147.483.648 ... 2.147.483.647]
  • long [-2^63 ... 2^63 -1]

Arithmetische Operationen und Wertebereiche

Vorsicht: Arithmetische Operationen dürfen den Wertebereich des Datentyps nicht überschreiten

Konsequenzen:

  • Programmabbruch
  • Variable enthält falschen Wert

Folgerung: Datentyp entsprechend wählen und Formeln eventuell umformen

Negative Zahlen

Anzahl darstellbarer Zahlen beschränkt (abhängig von Wortlänge)

Vorzeichenbit:

  • erstes Bit ("most significant bit") als Vorzeichen
    • 0 -> positiv
    • 1 -> negativ
  • Probleme:
    • es existieren 2 Darstellungen für Null, also 2 unterschiedliche Bitfolgen als Code für eine Zahl
    • Addier-/ Subtrahierwerk notwendig -> kein Algorithmus zur Darstellung einer Subtraktion per Addition
    • Logik erforderlich zur Erkennung von Addition oder Subtraktion

Einer-Komplement:

  • komplementäre Darstellung
    • einzelne Bits werden invertiert: 0->1; 1->0
  • Problem:
    • 2 Repräsentanten für Null

Zweier-Komplement:

  • Konvertierung und Addition mit 1
  • Eigenschaften:
    • eindeutige Repräsentation von Null

Gleitkommazahlen

Wertebereich für Gleitkommazahlen

  • float [-3.402823510^38 ... 3.402823510^38]
  • double [-1.79769310^308 ... 1.79769310^308]

Zahlen mit . -> automatisch als double interpretiert (z.B. -1.5 11.0)

Formatangaben:

  • Zahlen müssen als float gekennzeichnet werden -> f anhängen (z.B. 1f 3.14f)
  • mit d oder D als double gekenzeichnet (z.B. 5d -3.5D)

spezielle Werte:

  • Float.NEGATIVE_INFINITY
  • Float.POSITIVE_INFINITY
  • Float.NaN (Not-a-Number)

Beispiel:

 float fva11 = 10.0;
 float fva12 = 0.0;
 float fva13 = 0.0;
 float fres1, fres2;

 fres1 = fva11 / fva12;  // Ausgabe: Infinity
 fres2 = fva12 / fva13;  // Ausgabe: NaN

Wahrheitswerte (boolean)

Wertebereich: true & false

logische Operationen:

  • Konjunktion &&
  • Disjunktion ||
  • Negation !

Vergleichsoperationen

  • Gleichheit ==
  • Ungleichheit !=
  • kleiner <
  • größer >
  • kleiner gleich <=
  • größer gleich >=

Boolesche Ausdrücke

  • boolesche Ausdrücke werden gebildet mithilfe von
    • Vergleichsoperationen
    • logische Operationen
  • boolesche Ausdrücke können mithilfe bestimmter Regeln umgeformt werden (z.B. DeMorgan)

Beispiel:

 float x = 5.0 f,
       y = 18.0f;
 int   z = 7;
 boolean a,b;

a = true;
b = (x > y) && (x < z) || (x == y) || a;  // Ausgabe liefert true

Erklärung: && bindet stärker als || -> Konjunktion hat die höhere Präzedenz

Auswertung:

  • boolesche Ausdrücke liefern Wahrheitswerte als Ergebnis
  • Ausdrücke können aus mehreren Operanden bestehen
    • Auswertung erfolgt sequentiell -> von links nach rechts
    • Auswertung ggf. abgebrochen, falls Ergebnis feststeht und sich nicht ändern kann

Beispiel:

 int x = 0;
 ...

... (x != 0) && ( y  / x > 1)

Erklärung:

  • (x != 0) && ergibt immer false
  • Operand ( y / x > 1) nicht mehr ausgewertet -> Division durch 0 verhindert

Zeichen (char)

Datentyp speicher jeweils ein einzelnes Zeichen

Wertebereich:

  • Groß-/ Kleinbuchstaben
  • Ziffern
  • Satzzeichen
  • Sonder-/Steuerzeichen

Hinweis: Java verwendet Zeichen vom Unicode (65536 Zeichen)

Notation:

  • Zeichen werden mit Hochkomma geschrieben (z.B. 'a', 'D', '!' , '4' , '+', ...)
  • Steuerzeichen werden durch back-slash eingeleitet (z.B. '\n' (Zeilenumbruch), '\t' (Tabulator), ...)
  • Hilfszeichen ebenfalls mit back-slah eingeleitet (z.B. ''' (Apostroph), '\' (back-slash), ...)

Zeichenkette (String)

String ist kein primitiver Datentyp!!

Beispiel:

Erzeugung von Strings durch Zeichenketten in Anführungszeichen

String s    = "Hallo ",
       name = "Peter";

Konkatenation (Aneinanderreihung von Zeichenketten)

String hello = "Hallo " + name;

Format:

  • Klasse String stellt Funktionen zu Verfügung
  • Aufruf von Funktionen auf Objekte vom Typ String

geg,:

String s1, s2;
int j, k;
char c;

s1.equals(s2);            // boolesche Funktion (true: wenn s1 exakt gleich wie s2, sonst false)
s1.equalsIgnoreCase(s2);  // boolesche Funktion (Funktion siehe oben, Groß-/Kleinschreibung gleichwertig)
s1.length();              // liefert Ergebnis vom Typ int mit Anzahl der Zeichen in s1
s1.charAt(k);             // liefert Ergebnis vom Typ char, entspricht Zeichen an der k-ten Position von s1
s1.substring(j, k);       // liefert Ergebnis vom Typ String, String enthält Zeichen von den Position j,j+1 ... k-1
                          // k wird nicht gelesen
s1.indexOf(s2);           // liefert Ergebnis vom Typ int 
                          // wenn s2 Substring von s1 -> liefert Position des Substrings in s1, sonst -1
s1.indexOf(c);            // suche nach Zeichen c in s1
s1.indexOf(c,k);          // suche nach Zeichen c in s1 ab Position k in s1
s1.toUpperCase();
s1.toLowerCase();         // liefert Ergebnis vom Typ String 
                          // wie s1 im Zeichen konvertiert wurde, die nicht der Zeichenform des Ziels entsprechen
s1.trim();                // liefert Ergebnis vom Typ String,
                          // neue Zeichenkette, bei der alle leer-druckenden Zeichen (z.B. Leertaste) entfernt wurden

Beispiel:

String a = "text",
       b = "text";
String c = new String("text"); // generiert ein neues Objekt vom Typ String

System.out.println(a == b);       // Ausgabe liefert true
System.out.println(a.equals(b));  // Ausgabe liefert true
System.out.println(a == c);       // Ausgabe liefert false
System.out.println(a.equals(b));  // Ausgabe liefert true

Implizite Typkonvertieung

  • Operatoren lassen sich nicht nur auf Operanden des selben Datentyps verwenden
    • werden typkompatible Operanden durch Operator verknüpft -> implizite Datentyp-Anpassung
    • Typkonversion -> auf allgemeineren Datentyp

Konvertierungsschema

byte -> short -> int 
        char  -> int -> long -> float -> double

char/double/boolean ---> String

Besonderheiten:

  • Typkonversion zu String ist eigentlich keine implizite Typkonversion
  • Reihenfolge der Operatoren muss beachtet werden

Beispiel:

System.out.println(17 + " und " + 4); // Ausgabe liefert: 17 und 4
System.out.println(17 + 4 + " und "); // Ausgabe liefert: 21 und

Explizite Typkonvertierung (casting)

Typkonvertierung mit Genauigkeitsverlust oder Bedeutungsänderung.

  • Umwandlung nicht in implizit möglich
  • vom Programmierer explizit vorgenommen
  • gewünschte Datentyp in Klammern dem Ausdruck vorangestellt

Beispiel:

double x = 65.2d;
int    i = (int) (x / 3.0); // liefert Ergebnis 21
char   y = (char) (int) x;  // liefert Ergebnis 'A'

Notiz: vorsichtig verwenden -> wenn möglich ganz vermeiden

Aufzählungstypen (Enumerationen)

  • Möglichkeit zur Definition neuer Datentypen und Klassen
  • Aufzählung enum ist ein Typ mit einer festgelegten Liste der möglichen Werte
  • Definition kann nicht innerhalb eines Unterprogramms erfolgen
  • sie kann außerhalb der main()-Routine platziert werden

Allgemein:

enum <enum-Typ-Name> {<Werte-Liste>}

Erläuterung:

  • : beliebiger einfacher Bezeichner
  • : jedes Element einfacher Bezeichner, Listenelemente durch Komma getrennt
  • Konvention: Werte der Aufzählung in Großbuchstaben geschrieben

Beispiel:

enum Season {SPRING, SUMMER, FALL, WINTER}

Definition:

  • enum ist technisch gesehen eine Klasse
  • Werte einer enum-Variable sind technisch gesehen Objekte
  • als Objekte können sie Unterprogramme oder Funktionen enthalten, die auf Objekte des Typs enum ausgeführt werden können

Beispiel 1:

enum Day {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
  // Definition des enum-Typs Day außerhalb der Methode

public static void main (String[] args) {

            Day day;
            day = Day.SUNDAY    // Zuweisung kann nur die in der Typdeklaration definierten Werte verwenden
            System.out.println("Tag: " + dy + " ist der " + (day.ordinal()+1) + ". Tag der Woche");

} // end main

Beispiel 2: Aufzählung in switch-Anweisung

 enum Season {SPRING, SUMMER, FALL, WINTER};

 ...
 Season currentSeason = Season.FALL;
 switch (currentSeason) {
    case WINTER:                        //  (nicht Season.WINTER!)
       System.out.println("December, January, February");
    case SPRING:
       System.out.println("March, April, May");
    case SUMMER:
       System.out.println("June, July, August");
    case FALL:
       System.out.println("September, October, November");
       break;
}

Hinweis: Hier werden die Werte des Aufzählungstyps in den case labels nicht mittels und Selektor . angesprochen!!

Zählschleifen auf Aufzählungsmengen

for (<enum-Typ-Name> <Variable>:
     <enum-Typ-Name>.values() )
  <Anweisung>;

for (<enum-Typ-Name> <Variable> : <enum-Typ-Name>.values() ) {
  <Anweisungen>;
}

Erläuterung:

  • : lokal in der for-Schleife definiert (vom Typ )
  • .values() : Funktion, die eine Liste der Werte der Aufzählung liefert
  • values() ist eine statische Klassenfunktion von enum

Beispiel:

enum Day {MON, TUE, WED, THU, FRI, SAT, SUN};

... 
for (day d : Day.values() )
  System.out.println (d + " ist der " + (d.ordinal()+1) + ". Tag der Woche");
       // liefert Ergebnis: MON ist der 1. Tag der Woche
       //                   TUE ist der 2. Tag der Woche 
       //                   usw.
⚠️ **GitHub.com Fallback** ⚠️