Kapitel 4 Programmierkurs Datentypen und Operatoren Einschub Binärdarstellung Ganzzahlige Numerische Datentypen Logischer Datentyp Typumwandlung Rationale numerische Datentypen (Gleitkommazahlen) Der alphanumerische Datentyp char Birgit Engels, Anna Schulze ZAIK Universität zu Köln WS 07/08 1 / 62 Datentypen 2 Arten von Datentypen Wir unterscheiden hier wieder Arten von Datentypen: Bei der Deklaration einer Variablen legt der Datentyp fest: Primitive Datentypen: Welche Werte die Variable annehmen kann. I Wieviel Speicherplatz die Variable belegen darf. I I Welche Operationen auf die Variable angewendet werden dürfen. I Ganzzahlige numerische Datentypen: int, long, ... Logischer Datentyp: boolean Rationale numerische Datentypen: float, double, ... Alphanumerischer Datentyp: char Vordefinierte Datentypen (z.B. : BufferedReader, InputStreamReader) Damit auch implizit in welchen Anweisungen sie vorkommen kann (später). Selbstdefinierte Datentypen (z.B. : Greets, Age) 3 / 62 4 Vor-/Selbstdefinierte Datentypen Primitive Datentypen Bei sogenannten “primitiven” Datentypen tritt die Objektorientierung zunächst in den Hintergrund. Sie heissen auch “Standarddatentypen”, da sie von quasi allen Programmiersprachen mehr oder weniger äquivalent implementiert sind. Vor-/ Selbstdefinierte Datentypen stehen in engem Zusammenhang mit Objektorientierung und werden daher später behandelt. Vorgriff Klasse - Datentyp - Objekt: Jede (wie bisher gesehen) definierte Klasse XYZ spezifiziert einen eigenen Datentyp XYZ. Es können Variablen mit diesem Datentyp als deklariert werden: XYZ beispiel Solche Variablen sind Objekte vom Typ XYZ und werden Instanzen der Klasse XYZ genannt. Im einfachsten Fall möchte man mit Variablen eines solchen Datentyps ganze oder natürliche Zahlen darstellen. Diese müssen im Computer natürlich binär gespeichert werden. Reserviert ein solcher Datentyp n Bits Speicherplatz, so kann man entweder die 2n natürlichen Zahlen von 0 bis 2n − 1 oder die 2n ganzen Zahlen von −2n−1 bis 2n−1 − 1 darstellen. 5 / 62 Natürliche Zahlen: Binärcodierung Darstellung natürlicher Zahlen mit n Die Zahlen von 0 bis 2n − 1. Beispiel: n = 3 Dezimal Binär Dezimal Binär 0 000 1 001 3 011 4 100 6 110 7 111 6 Natürliche Zahlen: Zahlenkreis Bits: Dezimal 2 5 8 Addiere: 111 + 001 = 1000 n = 3 Bits: Höchstes Bit fällt weg: (111 + 001 = 000)bin (7 + 1 = 0)dez Binär 010 101 - Fehler durch “Überlauf” ! 0 7 000 111 8 = 23 ist mit 3 Bits (wegen der Darstellung der 0) nicht mehr darstellbar. 6 110 8 wäre in Binärdarstellung mit 4 Bits: 1000 010 Das erste Bit entfällt, bei 3-Bit-Darstellung und 000 entspricht bereits der Codierung der 0: Überlauf. 2 011 101 5 1 001 100 3 4 7 / 62 8 Ganze Zahlen - Vorzeichencodierung Ganze Zahlen - Einerkomplement 2. Möglichkeit: Einerkomplement (−x ist bitweises Komplement von +x). Beispiel: n = 3 Dezimal Binär Dezimal Binär 0 000 1 001 2 010 3 011 -0 111 -1 110 -2 101 -3 100 Gleicher Darstellungsbereich wie Vorzeichendarstellung Zur Darstellung von positiven ganzen Zahlen muss nun noch die für negative hinzu kommen. 1. Möglichkeit: 1. Bit codiert Beispiel: n = 3 Dezimal Binär Dezimal 0 000 1 2 010 3 -0 100 -1 -2 110 -3 Vorzeichen. Darstellung ganzer Zahlen von Binär 001 011 101 111 2n−1 0 doppelt codiert bis 2n−1 − 1. 1. Bit codiert immernoch Vorzeichen. 0 doppelt codiert. 1. und 2. Möglichkeit: Schwierige Implementierung von arithmetischen Operationen, da jede Zahl (positiv, negativ) anders interpretiert werden muss. Daher: Zweierkomplementdarstellung. 9 / 62 Ganze Zahlen - Zweierkomplement 10 Ganze Zahlen: Zahlenkreis im Zweierkomplement Zweierkomplement formal definiert: Höchstwertiges Bit bn hat Wertigkeit −1 3. Möglichkeit: Zweierkomplement (−x ist bitweises Komplement von +x + 1). Beispiel: n = 3 Dezimal Binär Dezimal Binär 0 000 1 001 2 010 3 011 -1 111 -2 110 -3 101 -4 100 0 nicht mehr doppelt codiert! Alle anderen Bits bi 1, d.h. x = −bn ∗ 2n + bn−1 ∗ 2n−1 + · · · + b0 Beispiel: 110 = −1 ∗ 22 + 1 ∗ 21 + 0 ∗ 20 = −4 + 2 + 0 = −2 0 -1 000 111 -2 1 001 110 010 2 Gewonnene “freie” Codierung für zusätzliche negative Zahl −4 011 101 −4 statt +4 : 1. Bit codiert immernoch Vorzeichen. -3 100 3 -4 11 / 62 12 4.2 Ganzzahlige numerische Datentypen Typ byte short int long Anz Bits 8 16 32 64 Min -128 -32768 -2147483648 < −1018 Gültiger Zahlenbereich (Over-/Underflow) Werden die Grenzen (min./max. darstellbare Zahl) des gültigen Zahlenbereichs eines Datentyps z.B. durch Zuweisung einer zu großen oder zu kleinen Zahl zu einer Variable des Typs verletzt entsteht ein sogenannter Über-/Unterlauf bzw. Over-/Underflow (Vorstellung: Bitdarstellung als Kreis → Übung): Max 127 32767 2147483647 > 1018 Overflow: Wir sehen, dass für Standarddatentypen n = 8 < 16 < 32 < 64 < . . . ist. Diese n Bits werden in Java jeweils für die ganzen (vorzeichenbehaftete) Zahlen von −2n−1 bis 2n−1 − 1 verwendet. Die Asymmetrie zwischen kleinster und größter darstellbarer Zahl eines Typs wird durch die Darstellung der “0” bedingt. Bitdarstellung einer zu großen Zahl erfordert mehr Bits als verfügbar. Bits werden abgeschnitten: Darstellung entspricht kleinerer Zahl. Bitdarstellung wird auch als kleinere Zahl (meist sogar wegen Darstellung als negative Zahl!) interpretiert. Underflow: Analog mit zu kleiner Zahl. 13 / 62 Operanden für ganze Zahlen I - Arithmetische Operationen 14 Kurzschreibweisen Für häufig benutzte Ausdrücke existieren Kurzschreibweisen: Operator + + * / % = Beispiel +i -i a+b a-b a*b a/b a%b x=a+b Inkrementierung/Dekrementierung: int i=0; i = i + 1; entspricht: i= i - 1; Bedeutung Vorzeichen (kann weggelassen werden) Vorzeichen Summe Differenz Produkt ganzzahlige Division Rest der ganzzahligen Division (Modulo) Zuweisung int i=0; i++; i--; Selbsbezügliche Addition/Subtraktion/... mit beliebigem 2. Wert: Operator += -= *= /= %= Diese Operatoren ermöglichen eine Art von Anweisung: Die Zuweisung arithmetischer Ausdrücke. 15 / 62 Beispiel a+=b a-=b a*=b a/=b a%=b Bedeutung a=a+b a=a-b a=a*b a=a/b a=a%b 16 Ganzzahlige Operanden: IntOps.java Ganzzahlige Operanden: IntOps.java 1. public static void main(String[] args) 2. { 3. int a=1, b=3, c=5, d=10; 4. System.out.println( a + ‘‘ ’’ + b + ‘‘ ’’ + c + ‘‘ ’’ + d ); 5. a++; 6. b+=a; 7. d=d/c; 8. a=b%d; 9. System.out.println( a + ‘‘ ’’ + (b-a) ); 10. } 1. public static void main(String[] args) 2. { 3. int a=1, b=3, c=5, d=10; 4. System.out.println( a + ‘‘ ’’ + b + ‘‘ ’’ + c + ‘‘ ’’ + d ); 5. a++; 6. b+=a; 7. d=d/c; 8. a=b%d; 9. System.out.println( a + ‘‘ ’’ + (b-a) ); 10. } 1 3 5 10 14 1 3 5 10 14 Der Wert b-a wird berechnet und auf dem Bildschirm ausgegeben, aber nicht gespeichert. 17 / 62 Ganzzahlige Operanden: IntOps.java 18 Ganzzahlige Operanden: IntOps.java 1. public static void main(String[] args) 2. { 3. int a=1, b=3, c=5, d=10; 4. System.out.println( a + ‘‘ ’’ + b + ‘‘ ’’ + c + ‘‘ ’’ + d ); 5. a++; 6. b+=a; 7. d=d/c; Merke: Kurze, gleichartige 8. a=b%d; kombinierte Deklarationen und 9. System.out.println( a + ‘‘ ’’ + (b-a) ); Initialisierungen zusammenfas10. } sen. 1. public static void main(String[] args) 2. { 3. int a=1, b=3, c=5, d=10; 4. System.out.println( a + ‘‘ ’’ + b + ‘‘ ’’ + c + ‘‘ ’’ + d ); 5. a++; 6. b+=a; 7. d=d/c; 8. a=b%d; 9. System.out.println( a + ‘‘ ’’ + (b-a) ); 10. } 1 3 5 10 14 1 3 5 10 14 19 / 62 Merke: Ausgabe von Variablen mit System.out.println(var) ohne “ ”. und Zusammensetzen von Ausgaben mit System.out.println(var + ‘‘ ’’) 20 Kurzschreibweisen II Inkrement/Dekrement: InkDekOps.java Für die Inkrementierung/Dekrementierung Kurzschreibweisen: int i=0; ++i; entspricht --i; nicht: 1. public static void main(String[] args) 2. { 3. int a=1, b=1; 4. System.out.println( ‘‘a: ’’ + a++ ); 5. System.out.println( a ); 6. System.out.println( ‘‘b: ’’ + ++b ); 7. } existieren weitere int i=0; i++; i--; Dies ist wichtig, falls die Inkrementierung/Dkrementierung innerhalb komplexerer Anweisungen ausgeführt werden: Im Ersten Fall wird zuerst In-/Dekrementiert und dann der (neue) Wert von i weiterverwendet, im zweiten Fall wird zuerst der alte Wert von i verwendet und dann In-/Dekrementiert. 1 2 2 21 / 62 Inkrement/Dekrement: InkDekOps.java 22 Inkrement/Dekrement: InkDekOps.java 1. public static void main(String[] args) 2. { 3. int a=1, b=1; 4. System.out.println( ‘‘a: ’’ + a++ ); 5. System.out.println( a ); 6. System.out.println( ‘‘b: ’’ + ++b ); 7. } 1. public static void main(String[] args) 2. { 3. int a=1, b=1; 4. System.out.println( ‘‘a: ’’ + a++ ); 5. System.out.println( a ); 6. System.out.println( ‘‘b: ’’ + ++b ); 7. } 1 2 2 1 2 2 Der Wert von a wird zuerst ausgegeben, dann inkrementiert (vgl. 2. Ausgabe von a). 23 / 62 Der Wert von b wird noch vor der Ausgabe inkrementiert. 24 Operanden für ganze Zahlen II - Vergleichsoperationen 4.3 Logischer Datentyp boolean Java besitzt den logischen Datentyp boolean : Operator </<= >/>= != == = Beispiel a<b/a<=b a>b/a>=b a!=b a==b x=a<b Bedeutung Liefert wahr, Liefert wahr, Liefert wahr, Liefert wahr, Zuweisung Wertebereich: { true, false } falls falls falls falls a a a a kleiner(-gleich) b grösser(-gleich) b ungleich b ist gleich b ist Kann bei Zuweisungen von logischen Ausdrücken verwendet werden. Wird implizit bei Kontrollstrukturen verwendet. Logische Operatoren: Operator ! && || = Die Auswertung von Vergleichsoperationen liefert einen der logischen Werte wahr oder falsch. Die Zuweisung eines solchen Wertes erfordert links von = eine Variable des Typs boolean !. Beispiel !i a && b a || b a = a && b Bedeutung logische Negation logisches UND logisches ODER Zuweisung 25 / 62 Vergleichsoperanden: CompOps.java 26 Vergleichsoperanden: CompOps.java 1. public static void main(String[] args) throws IOException 1. public static void main(String[] args) throws IOException 2. { 2. { 3. int zahl; 3. int zahl; 4. boolean zwischen1und10; 4. boolean zwischen1und10; 5. System.out.println( ‘‘Ganze Zahl:’’ ); 5. System.out.println( ‘‘Ganze Zahl:’’ ); 6. {... Einlese-Anweisungen ... } 6. {... Einlese-Anweisungen ... } 7. zahl = Integer.parseInt(zahlString); 7. zahl = Integer.parseInt(zahlString); 8. zwischen1und10 = (zahl>=0) && (zahl<=10); 8. zwischen1und10 = (zahl>=0) && (zahl<=10); 9. 9. System.out.println( ‘‘Die Zahl liegt zwischen 0 und 10: ’’ + zwischen1und10 ); Vergleich auf Variablen vom 10. }//main Typ int. System.out.println( ‘‘Die Zahl liegt zwischen 0 und 10: ’’ + zwischen1und10 ); 10. }//main 27 / 62 28 Vergleichsoperanden: CompOps.java Vergleichsoperanden: CompOps.java 1. public static void main(String[] args) throws IOException 1. public static void main(String[] args) throws IOException 2. { 2. { 3. int zahl; 3. int zahl; 4. boolean zwischen1und10; 4. boolean zwischen1und10; 5. System.out.println( ‘‘Ganze Zahl:’’ ); 5. System.out.println( ‘‘Ganze Zahl:’’ ); 6. {... Einlese-Anweisungen ... } 6. {... Einlese-Anweisungen ... } 7. zahl = Integer.parseInt(zahlString); 7. zahl = Integer.parseInt(zahlString); 8. zwischen1und10 = (zahl>=0) && (zahl<=10); 8. zwischen1und10 = (zahl>=0) && (zahl<=10); System.out.println( ‘‘Die Zahl liegt zwischen 0 und 10: ’’ + zwischen1und10 ); Wird zu Typ boolean ausge10. }//main wertet! 9. 9. System.out.println( ‘‘Die Zahl liegt zwischen 0 und 10: ’’ + zwischen1und10 ); Können logisch weiter ver10. }//main knüpft werden. 29 / 62 Verwechslungsgefahr 30 4 Ganzzahlige Datentypen vs. 1 int Haben byte, short, int, long kennen gelernt. Operator == = Beispiel a==b x=a<b Nutzen in Beispielen nur int, da dieser Typ auch in der Praxis am gebräuchlichsten ist. Bedeutung Liefert wahr, falls a gleich b ist Zuweisung Nutzung von byte, short : Speicherplatz sparen (bei Speicherkritischen Geräten, z.B. Handys, oder grossen Eingaben für Algorithmen). Durch Tippfehler wird der Vergleichsoperator für den Test auf Gleichheit zweier Variablen == leicht zum Zuweisungsperator = und umgekehrt !!! Falls keine “normalen” Zahlen dargestellt werden sollen, sondern spezielle Dinge kodiert werden (z.B. Überschaubare Anzahl von Zuständen, Farben, ...). Nutzung von long, falls Wertebereich von int nicht ausreicht. 31 / 62 32 4.4 Typumwandlung (Typecast) I Expliziter Typecast Java ist eine strikt typisierte Sprache, d.h. jede Variable besitzt einen Typ. Dieser wird vom Compiler bei der Variablendeklaration “gelernt” und “erlaubt” danach nur: Explizite Typumwandlung: Einer Variable wird explizit der Neue Typ in Klammern vorangestellt: Zuweisungen von Variablen des gleichen Datentyps. short s=123; int i; i= (int) s; Operationen, die für den Typ der Variablen definiert sind. Operationen auf Variablen gleichen Typs. Manchmal ist es dennoch nötig (und sinnvoll!), andere Zuweisungen bzw. Operationen auszuführen, daher gibt es 2 Arten von Typumwandlung (Typecast): Normale Deklaration. Normale Deklaration. Zuweisung mit explizitem Cast von short auf int Achtung: Der Typecast (kurz: Cast) ändert nicht den deklarierten Typ der Variable, sondern ermöglicht nur die Zuweisung zu einer Variable anderen Typs bzw. die Anwendung einer Operation anderen Typs. Variable s ist immernoch vom Typ short und i vom Typ int ! Expliziter Typecast Impliziter Typecast 33 / 62 Impliziter Typecast Impliziter Typecast - Erlaubte Typen Für einige Datentypen gibt es Typen, auf die ein impliziter Cast erlaubt ist, d.h. bei typgemischten Zuweisungen oder Operationen wird vom Compiler jede Variable automatisch in einen der beteiligten Typen umgewandelt. Dieser ist fest definiert. Implizite Typumwandlung: Eine Variable wird einer anderen von anderem, erlaubten Typ zugewiesen oder eine Operation eines solchen Typs auf sie angwandt: short s=123; int i; i= s; 34 Beispiel byte, short, int, long: Normale Deklaration. Normale Deklaration. Zuweisung von short zu int Cast wie folgt erlaubt, da Wertebereich sich vergrössert: byte → short → int → long Der Typecast ändert auch hier nicht den deklarierten Typ der Variable !Variable s ist immernoch vom Typ short und i vom Typ int ! Cast wie folgt verboten, da Wertebereich sich verkleinert (Gefahr von Over-/Underflow): long 9 int 9 short 9 byte 35 / 62 36 Warnung Beispiel Typecast (IntCast.java) 1. public static void main(String[] args) 2. { 3. byte b; 4. short s=255; 5. int i=123456; 6. long l; 7. b = (byte) s ; 8. l = i ; 9. System.out.println( ‘‘Byte: ’’ + b + ‘‘ Short: ’’ + s ); 10. System.out.println( ‘‘Int: ’’ + i + ‘‘ Long: ’’ + l ); 11. } Impliziter Cast: I I I Auf nicht erlaubte Typen erzeugt Kompilierfehler. Auf erlaubte Typen kann ungewollt sein und fehlerhafte Effekte erzeugen (Beispiele später)! Typen können erlaubt sein, aber nur in sehr speziellen Fällen oder trickreicher Programmierung sinnvoll sein! Expliziter Cast: Compiler lässt auch Unsinniges zu. Die Sicherheit eines Typecasts muss der Programmierer verantworten ! Byte: -1 Short: 255 Int: 123456 Long: 123456 37 / 62 Beispiel Typecast (IntCast.java) 38 Beispiel Typecast (IntCast.java) 1. public static void main(String[] args) 2. { 3. byte b; 4. short s=255; 5. int i=123456; 6. long l; 7. b = (byte) s ; Expliziter Cast erforder8. l = i ; lich, da nicht sicher. 9. System.out.println( ‘‘Byte: ’’ + b + ‘‘ Short: ’’ + s ); 10. System.out.println( ‘‘Int: ’’ + i + ‘‘ Long: ’’ + l ); 11. } 1. public static void main(String[] args) 2. { 3. byte b; 4. short s=255; 5. int i=123456; 6. long l; 7. b = (byte) s ; Impliziter Cast, da sicher. 8. l = i ; 9. System.out.println( ‘‘Byte: ’’ + b + ‘‘ Short: ’’ + s ); 10. System.out.println( ‘‘Int: ’’ + i + ‘‘ Long: ’’ + l ); 11. } Byte: -1 Short: 255 Resultiert in Overflow für Int: 123456 Long: 123456 Byte-Variable. Byte: -1 Short: 255 Wert bleibt gleich in Int: 123456 Long: 123456 Long-Variable. 39 / 62 40 4.5 Gleitkommazahlen Rationale Numerische Datentypen (Gleitkommazahlen) Wie bereits am Beispiel einer Konstanten Im Computer wird eine rationale Zahl immer als Gleitkommazahl durch Vorzeichen, Mantisse und Exponent (zur Basis 2) repräsentiert. static final double PI=3.1415; gesehen, benötigen wir neben ganzen Zahlen natürlich auch rationale Zahlen. In Java gibt es für Gleitkommazahlen die 2 Typen float (Floating Point Number) und double (Double Precission): Jede Zahl x ∈ Q, x 6= 0 lässt sich schreiben als: x = s · m · 10e Bitanzahl für: Vorzeichen Mantisse Exponent Summe Bereich mit - Vorzeichen s ∈ {1, −1} - Mantisse m ∈ Q, 1 ≤ m < 10 - Exponent e ∈ Z. Da sich in ausgeschriebener Variante, die Position des Kommas je nach Exponent verändern würde, heisst diese Darstellung Gleikommazahl (Floating Point Number). float 1 23 8 32 1.4E − 45 − 3.4E 38 double 1 52 11 64 4.9E − 324 − 1.8E 308 41 / 62 Notation für Gleitkommazahlen 42 Vor- und Nachteile von Gleitkommazahlen Die Darstellung einer Gleitkommazahl im Java-Quelltext hat die Form: Vorzeichen (optional) Vorteile von Gleitkommazahlen: Vorkommastellen Der abgedeckte Zahlenbereich ist sehr gross. Dezimalpunkt Erlaubt dennoch hohe Präzision. Nachkommastellen Nachteile von Gleitkommazahlen: E Vorzeichen des Exponenten (optional) Bei Rechenoperationen entstehen in der Regel (wie bei den meisten reellen Rechnungen im Computer) Rundungsfehler. Ganzzahliger Exponent Die Rechenoperationen, insbesondere Addition und Subtraktion, sind erheblich aufwändiger. Variablen vom Typ float und double können auch Zahlen in gewöhnlicher Punktschreibweise: < vorkommastellen > . < nachkommastellen > zugewiesen werden. 43 / 62 44 Operanden für Gleitkommazahlen Prioritäten der Java Operanden Operanden für Gleitkommazahlen entsprechen den arithmetischen und vergleichenden Operanden für ganze Zahlen. Für die Beschreibung komplizierterer Ausdrücke (besonders ohne Bruchschreibweise), empfiehlt sich die Kenntnis der Prioritäten unter den Operanden. Einige Besonderheiten: Kurzschreibweisen Inkrement ++ und Dekrement -funktionieren (obwohl nicht so intuitiv) auch bei Gleitkommazahlem. Wollte Prioritätentabelle angeben, fand statt dessen: Der Operator / steht für Division (nicht ganzzahlig). Wegen Rundungsfehlern ist Prüfen auf Gleichheit == oder Ungleichheit != meist nicht sinnvoll. 45 / 62 Prioritäten der Java Operanden 46 Grundregeln Für die Beschreibung komplizierterer Ausdrücke (besonders ohne Bruchschreibweise), empfiehlt sich die Kenntnis der Prioritäten unter den Operanden. Der Zugriffsoperator . hat größte Priorität. Klammern haben zweithöchste Priorität und können jedem Ausdruck die gewünschte Priorität einräumen. Wollte Prioritätentabelle angeben, fand statt dessen: Es gilt Punkt- vor Strichrechnung. Kein Programmierer sucht nach seiner Präzedenz-Tabelle, um die Ausführungsreihenfolge von Operatoren zu überprüfen. Setzen Sie einfach Klammern, wenn Sie nicht sicher sind, und fertig. Gerade komplizierte Ausdrücke werden mit Klammerung leserlicher. Bei Unsicherheit immer Klammern. 47 / 62 48 Beispiel Rundungsfehler (FloatErr.java) Beispiel Rundungsfehler (FloatErr.java) 1. public static void main(String[] args) 2. { 3. float f1=1.234567E-7f, f2=1, f3=-f2; 4. float sum1,sum2; 5. sum1=(f1+f2)+f3; 6. sum2=f1+(f2+f3); 7. System.out.println( ‘‘(f1+f2)+f3: ’’ + sum1 ); 8. System.out.println( ’’f1+(f2+f3): ‘‘ + sum2 ); 9. } 1. public static void main(String[] args) 2. { 3. float f1=1.234567E-7f, f2=1, f3=-f2; 4. float sum1,sum2; 5. sum1=(f1+f2)+f3; 6. sum2=f1+(f2+f3); 7. System.out.println( ‘‘(f1+f2)+f3: ’’ + sum1 ); 8. System.out.println( ’’f1+(f2+f3): ‘‘ + sum2 ); 9. } (f1+f2)+f3: 1.1920929E-7 f1+(f2+f3): 1.234567E-7 (f1+f2)+f3: 1.1920929E-7 (f1+f2)+f3 : Zu eine kleinen Zahl f1+(f2+f3): 1.234567E-7 wird 1 addiert, dann wieder abgezogen: Präzisionsverlust 49 / 62 Beispiel Rundungsfehler (FloatErr.java) 50 float Zuweisung 1. public static void main(String[] args) 2. { 3. float f1=1.234567E-7f, f2=1, f3=-f2; 4. float sum1,sum2; 5. sum1=(f1+f2)+f3; 6. sum2=f1+(f2+f3); 7. System.out.println( ‘‘(f1+f2)+f3: ’’ + sum1 ); 8. System.out.println( ’’f1+(f2+f3): ‘‘ + sum2 ); 9. } Bei Zuweisung einer möglicherweise zu grossen/präzisen Konstante zu einer, gibt es (nur hier!) 2 Möglichkeiten des expliziten Casts: float f = 1676158.43141f float f = (float) 1676158.43141 Ohne eine dieser Varianten würde die Zahl als double interpretiert und ein Kompilierfehler ausgegeben. (f1+f2)+f3: 1.1920929E-7 f1+(f2+f3) : +1 und -1 werden zuf1+(f2+f3): 1.234567E-7 erst addiert und ergeben exakt 0. Es wird quasi keine Addition auf f1 ausgeführt: Kein Präzisionsverlust 51 / 62 52 Typumwandlung (Typecast) II Operanden und gemischte Typen I Expliziter Typecast ist wie bei den ganzen Zahlen auch hier und bei allen weiteren Datentypen möglich. Der erlaubte impliziter Typecast zwischen ganzzahligen numerischen Datentypen erweitert sich auf rationale Datentypen wie folgt: Jeder Operator kann nur auf gleichartigen Datentypen arbeiten Operationen und Zuweisungen können trotzdem gemischte Typen enthalten: int i = 1; double d = 2, e; e = i/d; Erlaubt: byte → short → int → long → float → double Dies ist so nur erlaubt, wenn alle beteiligten Typen standardmäß implizit in den gleichen Typ umgewandelt werden (Hier: double). Nicht erlaubt: double 9 float 9 long 9 int 9 short 9 byte Vor der Division i/d wird i automatisch in double umgewandelt. Weitere Typen können erlaubt sein, aber Fehlerquellen beinhalten. 53 / 62 Operanden und gemischte Typen II 54 Abrunden mit int-Cast Durch explizite Umwandlung von Gleitkommazahlen (double, float) in ganzzahlige Werte erhält man den ganzzahligen Anteil der Zahl: Andernfalls muss zusätzlich ein explitizer Typecast auftreten: int i = 1; double d = 2; float f = (float) i/d; Das Programmfragment: double d = 3.1415; int i = (int) d; System.out.prinln(d); Warum Cast (float) notwendig? 1. Bei Berechnung i/d wird i (erlaubterweise) implizit in double umgewandelt. 2. Das Ergebnis der Division ist damit auch automatisch ein double-Wert. 3. Die Zuweisung f=i/d ist daher nicht erlaubt (obwohl 0.5 ohne Probleme als float- Wert darstellbar ist. Gibt aus: 3 Bei gemischten Zuweisungen können unerwünschte implizite Umwandlungen in int auftreten, die ebenfalls diesen Effekt haben... 55 / 62 56 Beispiel gemischte Typen (MixedType.java Beispiel gemischte Typen (MixedType.java 1. public static void main(String[] args) 2. { 3. int i = 1; 4. double d = 2, e, a, b; 5. e = i/d; 6. float f= (float) (i/d); 7. a = i/2 ; 8. b = i/2.0 ; 9. System.out.println( ’’e: ‘‘ + e + ’’ f: ‘‘ + f); 10. System.out.println( ’’a: ‘‘ + a + ’’ b: ‘‘ + b); 11. } 1. public static void main(String[] args) 2. { 3. int i = 1; 4. double d = 2, e, a, b; 5. e = i/d; 6. float f= (float) (i/d); 2 wird als int interpretiert: / als 7. a = i/2 ; ganzzahlige Division ergibt 0 und wird 8. b = i/2.0 ; in +double umgewandelt. 9. System.out.println( implizit ’’e: ‘‘ e + ’’ f: ‘‘ + f); 10. System.out.println( ’’a: ‘‘ + a + ’’ b: ‘‘ + b); 11. } e: 0.5 f: 0.5 a: 0.0 b: 0.5 e: 0.5 f: 0.5 a: 0.0 b: 0.5 57 / 62 Beispiel gemischte Typen (MixedType.java 58 4.6 Der alphanumerische Datentyp char 1. public static void main(String[] args) 2. { 3. int i = 1; 4. double d = 2, e, a, b; 5. e = i/d; 6. float f= (float) (i/d); 2.0 wird als double interpretiert: i 7. a = i/2 ; wird implizit in double umgewandelt, 8. b = i/2.0 ; so dass / als rationale Division 0.5 als 9. System.out.println( ’’e: ‘‘ + e ergibt. + ’’ f: ‘‘ + double-Wert f); 10. System.out.println( ’’a: ‘‘ + a + ’’ b: ‘‘ + b); 11. } char-Variablen werden dazu verwendet, Zeichen darzustellen. Zeichen sind hier: Buchstaben, Ziffern, Sonderzeichen ... Typischerweise sind chars 1 Byte groß und können daher 256 verschiedene Werte repräsentieren. Dabei entsprechen die ersten 128 Zeichen den Zeichen der ASCII-Tabelle (s.o.). Die nächsten 128 Zeichen sind Länderspezifischen Erweiterungen vorbehalten. Java verwendet einen 2 Byte langen char-Typen, der die 65536 des Unicode umfasst. So können quasi alle bis heute bekannten Schriftzeichen anhand einer Eindeutigen Unicode-Nummer dargestellt werden. e: 0.5 f: 0.5 a: 0.0 b: 0.5 59 / 62 60 Nutzung von char char vs. String Zeichenkonstanten (Variablen vom Typ char) können wie folgt Werte zugewiesen werden: Bisher kennen wir haben wir Zeichenketten in Form des Datentyps String kennen gelernt. Unterschiede: Zeichen in einfaches Hochkomma eingeschlossen: char c = ’A’ ASCII-Code des Zeichens: char c = 65 Ausgabe beider Zuweisungen: A I I I String Zeichenkette, char einzelnes Zeichen. String in “ ”, char in ’ ’ String i. Ggs. zu char kein primitiver Datentyp. Der Datentyp String ist ein zusammengesetzter Datentyp. Manche Zeichen müssen besonders codiert werden, z.B. werden die Zeichen ’, ”oder \ als \’, \”und \\ dargestellt. Ein String besteht aus einem Feld (Array) von char Variablen (später) und besitzt eigene Operatoren. Weiter gibt es Sonderzeichen wie \n für Zeilenvorschub und \t für ein Tabulatorzeichen. Mehr im Kapitel Ein- und Ausgabe. 61 / 62 62