2. Typen, Operationen und Zuweisungen

2. Typen, Operationen und Zuweisungen

Dieser Unterrichtsblock beschäftigt sich mit den Grundlagen von Variablen und ihren Belegungen.

Motivation zu den Themen dieses Blocks

Am Ende dieses Blocks haben Sie ein Grundverständnis von

  • Schlüsselwörter: Vorbelegte Worten in der Sprache Java
  • Variablen: Den Behältern von Werten
  • Zuweisungen: Das Belegen dieser Behälter mit Werten
  • Typen: Die unterschiedlichen Arten von Informationsbehältern
  • Literalen: Die textuelle Beschreibung von Werten
  • Operatoren: Die Verknüpfung von Werten um Berechnungen vorzunehmen
Stefan Schneider Sun, 06/20/2010 - 14:52

2.1 Schlüsselwörter, Literale, Variablennamen, Kommentare

2.1 Schlüsselwörter, Literale, Variablennamen, Kommentare

Motivation

Auf dieser Seite lernen Sie wie man die wichtigsten Teile der Sprache Java nennt.

Zum Beispiel die Teile einer Zuweisung:

Schlüsselwörter

Java Schlüsselwörter sind:

abstract continue for new switch
assert default if package synchronized
boolean do goto private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while

 

Die Schlüsselworte in Kategorien gruppiert ergeben:

Diagramm Schlüsselworte

 

The Schlüsselworte const und goto sind reserviert auch wenn sie im Moment nicht benutzt werden.

true und false sind technisch gesehen boolsche Literale. (Java 7 Spez. §3.10.3). Das Gleiche gilt für das null Literal (Java 7 Spez. §3.10.7).

Namen (Identifier)

Siehe Java Spezifikation: Identifier

Regeln für Namen in Java:

  1. Gültige Namen dürfen nur aus Buchstaben, Ziffern, und den Zeichen "_" und "$" bestehen. Sie dürfen beliebig lang sein.
  2. Das erste Zeichen muss ein Buchstabe, "_" oder  "$" Zeichen sein.
  3. Leerzeichen sind nicht erlaubt
  4. Schlüsselworte der Sprache Java dürfen nicht verwendet werden. (Boolsche Literale und das null Literal dürfen auch nicht verwendet werden)
  5. Groß- und Kleinschreibung von Buchstaben wird unterschieden

Literale

Literale dienen zum Beschreiben konkreter Werte in der Sprache Java.

Die Syntax wurde mit Hilfe von regulären Ausdrücken beschrieben.

Literale
Syntax Typ Beispiel
number int 17, -17
number[l|L] long 24l, -24L
0[x|X]hex int in Hexadezimaldarstellung 0x01234567890ABCDEF
0octal int in Oktaldarstellung 071
0b{0|1} int in Binärdarstellung (erst seit Java 7, JSR 334) 0b101010101010
[+|-][number].number double (Fließkommazahl) -3.1415
[+|-]number[f|F] float (Fließkommazahl) -3.1415F
[+|-]number[d|D] double (Fließkommazahl) -3.1415E13D
[+|-]number int mit Vorzeichen (signed number) -3, +3
[+|-]number.number[e|E][+|-]number Exponentendarstellung -3.1415E10
'character' einzelnes Zeichen 'a'
"characters" Zeichenkette "aB10"
"" Leere Zeichenkette ""
\b Zeichenposition 1 nach links (back space)  
\t Tabulator  
\n Zeilenvorschub  
\f Seitenvorschub  
\r Wagenrücklauf  
\" Doppeltes Anführungszeichen  
\' Einfaches Anführungszeichen  
\\ Schrägstrich rückwärts  
\uNNNN Unicodezeichen (NNNN in hexadezimal)  
true Boolscher Wert true
false Boolscher Wert false

 

Zahlen

  • Ganzzahlen
    • Dezimalzahlen mit den Ziffern 0 bis 9 und Vorzeichen
      • Beispiele: 1, -19, 45678
    • Hexadezimalen mit den Ziffern 0 bis 9 und als Ziffer interpretierte Zeichen a bis f und einer Präfix 0x
      • Beispiele: 0x1, 0xffff, 0xcafebabe
    • Oktalzahlen mit den Ziffern 0 bis 7 und einer vorgestellten 0
      • Beispiel 012 (=1*81+2*80=1010 ,  077 (=7*81+7*80=6310)
  • Gleitkommazahlen,
    • dargestellt im vertrauten Dezimalsystem
      • Nachkommateil durch Punkt abgetrennt
        • Beispiel: 5.4, 6. (stellt Gleitkommazahl 6.0 dar)
    • Zehnerpotenzen zur Basis Zehn werden mit dem Buchstaben e oder E bezeichnet
      • Beispiel: 4E-2 stellt 4*10-2= 0.04 da.

Ab JDK 7: Gruppierung in Zahlenliteralen

Seit JDK 7 sind durch die Integration des Projekts "Coin" (JSR 334) die Gruppierung von Zifferngruppen in Zahlenliteralen durch den Tiefstrich '_' möglich.

Der JSR Spezifikation entnommene Beispiele der neuen Syntax:

1234_5678
1_2_3_4__5_6_7_8L
0b0001_0010_0100_1000
3.141_592_653_589_793d
0x1.ffff_ffff_ffff_fP1_023 // Double.MAX_VALUE

nicht erlaubt sind:

_1234
0x_1234
1234_
0x1.0_p_-1022

Warnung: Java 7,8,9 werden noch nicht überall eingesetzt:

  • Bei Verwendung von javac Javaübersetzern von JDK 5 oder 6 wird diese Syntax nicht akzeptiert
  • Bei Verwendung des Javaübersetzers mit Optionen zur Verwendung alter Syntaxstandards wie javac -source 1.6 in JDK 7,8,9 wird die neue Syntax auch nicht akzeptiert werden!

Zeichen und Zeichenketten

  • Zeichen: Ein einzelnes Zeichen (char) wird in einfachen Hochkommas geschrieben
    • Beispiele: 'a', '2', '!', ' '
  • Zeichenketten: in Doppelhochkamma eingeschlossene Folgen von Zeichen
    • Beispiele: "Das ist eine Zeichenkette", 
    • Tipp: Zeichenketten dürfen nicht über den Zeilenrand hinwegreichen!

Zeichenketten ohne Namen nennt man Literale.

Kommentare

Kommentare erlauben das Dokumentieren eines Programmes. Sie werden vom Übersetzer ignoriert.

Java benutzt das Kommentarkonzept auch zur Generierung von Dokumentation. Dokumentationskommentare sind eine Sonderform der Kommentare und werden im Abschnitt zur Dokumentation vorgestellt.

Zeilenkommentare, Zeilenendkommentare

Zeilenkommentare beginnen nach dem doppelten Schrägstrich //. Der Javaübersetzer wird alle Zeichen hinter diesem Kommentarzeichen bis zum Ende der Zeile ignorieren.

Beispiel:

int a = 17; // Dies ist ein Zeilenendkommentar
// Dieser Kommentar umfasst eine ganze Zeile
int b = 18;

Mehrzeilige Kommentare

Java erlaubt es eine ganze Reihe von Zeilen als Kommentar zu kennzeichnen. Mehrzeilige Kommentare werden mit den Zeichen "/*" (Schrägstrich Stern) eingeleitet und mit der Zeichenkombination "*/" (Stern Schrägstrich) beendet. Hiermit kann man ganze Bereiche als Kommentar markieren.

Beispiel:

/* Hier beginnt ein Kommentar
diese Zeile gehört zum Kommentar
int i=1; diese Zeile wird nicht als Befehl sondern als Kommentar verarbeitet
der Kommentar endet in der nächsten Zeile
*/

 

Stefan Schneider Sun, 07/04/2010 - 17:24

2.2 Datentypen und Wertebereiche

2.2 Datentypen und Wertebereiche

Die Typen die ein Entwickler in Java vewendet sind entweder primitive Datentypen oder komplexe Datentypen. Die beiden Kategorien unterscheiden sich in den folgenden Eigenschaften:

  Primitiver Datentyp Komplexer Datentyp (Javaklassen)
Operatoren viele hochoptimierte Operationen Nur Operatoren für Objekte (Vergleich, Referenzierung). Ansonsten Methoden der Klasse
Lebensdauer hängt vom umgebenden Block, bzw. Objekt ab liegt im Freispeicher. Lebensdauer hängt von der letzten Referenz auf Objekt ab
Speicherverbrauch konstant variabel
Speicherort im Prozedurblock oder im Objekt einer Klasse immer im Freispeicher (Heap)
Syntax immer klein geschrieben Systemklassen beginnen immer mit Großbuchstaben (Es ist guter Stil auch Benutzerklassen mit einem Großbuchstaben beginnen zu lassen).

Im nachfolgenden Diagramm wird die Klassifikation der wichtigsten Typen gezeigt:

Klassifikation der Javatypen

Die nächsten beiden Abschnitte behandeln die hier gezeigten Typen. Der dritte Abschnitt beschäftigt sich mit den Risiken von Zuweisungen zwischen Datentypen mit unterschiedlichen Wertebereichen.

Stefan Schneider Sun, 06/20/2010 - 16:43

2.2.1 Primitive Javatypen

2.2.1 Primitive Javatypen

Ganzzahlige Datentypen

Ganzzahlige Datentypen
Datentyp Bits Wertebereich Wertebereiche Konstante min. Konstante max.
byte 8=1 byte -27 bis 27-1 -128 bis +127

Byte.MIN_VALUE

Byte.MAX_VALUE

short 16=2 byte -215 bis 215-1 -32768 bis +32767

Short.MIN_VALUE

Short.MAX_VALUE

char 16=2 byte 0 bis 216-1 0 bis +65535 (Sonderfall!)

Character.MIN_VALUE

Character.MAX_VALUE

int 32=4 byte -231bis 231-1 -2147483648 bis +2147483647

Integer.MIN_VALUE

Integer.MAX_VALUE

long 64=8 byte -263 bis 263-1 −9,223,372,036,854,775,808 to +9,223,372,036,854,775,807

Long.MIN_VALUE

Long.MAX_VALUE

Die maximalen und minimalen Werte der Ganzzahltypen ergeben sich aus der Anzahl der Bits und der internen binären Präsentation. Dies ist am Beispiel des 8-Bit Typen Byte aufgeführt:

Java verwendet für die Darstellung negativer Ganzzahlen das Zweierkomplement. Der Vorteil des Zweierkomplement besteht in der einfacheren Implementierung von Arithmetikeinheiten in Prozessoren. Durch das Zweierkomplement kann das Vorzeichenbit bei Additionen und Subtraktion wie ein regulärers Bit des Wertebereichs behandelt werden.

Dies kann man gut am Beispiel der Zahl -1 erkennen. Addiert man zur Zahl -1 (Binärdarstellung 11111111) eine 1 (Binärdarstellung 00000001) so ergibt durch den Übertrag eine 0 (Binärdarstellung 00000000).

Die Anwendung zur Rechten ist in der Lage alle Ganzzahltypen in die Binärdarstellung umzuwandeln.

Das Vorzeichenbit wird in Rot dargestellt. Bei allen Typen die mehr als 16 Bit erfordern wird die Ausgabe nach 16 Bit umgebrochen. Das Bit mit der höchsten Ordnung wird zuerst ausgegeben. Das Bit mit der niedrigsten Ordnung wird am Ende ausgegeben.

Hinweis

Der Typ char ist ein Zahlentyp. Man muss jedoch genau ein beliebiges Zeichen (Buchstabe) im Eingabefenster eingeben. Der Typ char unterscheidet sich vom Typ short in der Benutzereingabe und im Wertebereich.

 Zum Herunterladen: BinaerIntApplet.jar

Starten Sie die Anwendung mit einem Doppelclick im Download Ordner oder öffen ein Terminal und führen den folgenden Befehl im Download Ordner aus:

java -jar BinaerIntApplet.jar

Es sollte ein Fenster erscheinen, dass ähnlich dem folgenden Fenster aussieht:

Screen shot BinaerIntApplet

Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole.

Fließkomma-Standarddatentypen

Die Zahlendarstellung der Fließkommazahlen geschieht nach der Norm IEEE 754 getrennt nach Bits für Vorzeichen (V), Mantisse und Exponent mit unterschiedlicherAnzahl von Bits abhängig vom Typ nach der Regel:

z= (-1)V*Mantisse*2Exponent

Fließkomma-Standarddatentypen
Datentyp Bits V
(bits)
Mantisse
(bits)
Exponent
(bits)
Zahlenbereich Dezimalstellen in Mantisse
float 32=4 Byte 1 23 8 ≈-3.4*1038 bis +3,4*1038 7
double 64=8 Byte 1 52 11 ≈-1.7*10308 bis +1.7*10308 15

Die Minimal- und Maximalwerte als Konstanten können über die Attribute MIN_VALUE und MAX_VALUE der Klassen Float und Double abgerufen werden.

Die Berechnung der dezimalen Werte ist für den menschlichen Betrachter nicht so einfach wie die Umwandlung von Ganzzahlen.

  • Der Exponent ist um 127 verschoben um auch negative Zahlen darstellen zu können.
  • Bei der Mantisse wurde im Diagramm eine symbolische (rote) Eins eingefügt, die nicht Teil der 32 Bit Muster ist. Jede Mantisse muss mit einer führenden 1 beginnen damit sie normalisiert ist. Da dieser Wert immer konstant ist muss man ihn nicht extra im 32 bit Wort speichern.

Der IEEE 754 Standard ist recht anschaulich in Wikipedia beschrieben.

Eine 32 Bit Fließkommazahl berechnet sich nach IEEE 754 wie folgt:

= (-1)Vorzeichen*2(Exponent-127)*Mantisse

Für den 32 Bit Typ float ergibt sich so nach dem Standard IEEE 754 das folgende Bitmuster für verschiedene Werte:

 

Das Applet zur Rechten ist in der Lage 32 Bit Fließkommazahlen in die Binärdarstellung umzuwandeln.

Die Knöpfe auf der rechten Seite erlauben die Eingabe von Extremwerten wie

  • NaN: Not a Number (z,Bsp das Ergebnis der Wurzel von -1
  • positiv, negativ unendlich
  • Größter Wert
  • Kleinster Wert der noch größer als Null ist

 

 

 Zum Herunterladen: BinaerFloatApplet.jar

Starten Sie die Anwendung mit einem Doppelclick im Download Ordner oder öffen ein Terminal und führen den folgenden Befehl im Download Ordner aus:

java -jar BinaerFloatApplet.jar

 Es sollte ein Fenster erscheinen, dass ähnlich dem folgenden Fenster aussieht:

Screenshot BinaerFloatApplet

Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole

Wahrheitswerte

Wahrheitswerte
Datentyp Bits Wertebereich Werte Konstante
boolean 8 (in der Oracle VM) wahr oder falsch true,false Boolean.FALSE, Boolean.TRUE

Die Anzahl der allokierten Bits hängt von der Implementierung ab (Siehe Spezifikation).

Wichtig: Alle Vergleiche (z.Bsp. (a<b) ) haben als Ergebnis einen boolschen Wert!

Zeichen

Java behandelt einzelne Zeichen intern als ganze Zahlen. Man kann auf den Typ char alle Operationen anwenden die auch für Zahlen erlaubt sind. Der wesentliche Unterschied zum Typ short besteht in der Eingabe und Ausgabe, sowie im Wertebereich. Hier werden lexikalische Zeichen ein- oder ausgegeben. 

Wichtiger Sonderfall: Der Typ char benutzt 16 Bit zum kodieren wie auch der Typ short. Die Wertebereiche unterscheiden sich jedoch. Der Typ char kodiert nur positive Werte. Im Englischen wird ein solcher Typ "unsigned" gennannt. Es ist ein Typ ohne Vorzeichenbit.

Zeichen
Datentyp Bits Wertebereich Werte  Kommentar 
char 16 UC='\u0000' bis '\uffff' 16 Bit Unicode 4.0 Basic Multilingual Plane (BMP)   "supplementary character" Unterstützung seit JDK 1.5

 

Stefan Schneider Sat, 10/29/2011 - 14:46

Anonymous (not verified)

Sun, 12/16/2012 - 13:21

Wieso werden für den Datentyp boolean 8 Bits benötigt? Eigentlich würde doch 1 Bit ausreichen.

Sie haben recht.
Alle Prozessoren auf denen man Java ausführen kann haben Registergrößen zum Rechnen von 32 oder 64 Bit.
Selbst alte oder einfache Prozessoren haben Registergrößen von 8 oder 16 Bit.
Das Laden und Speichern eines beliebigen Datums aus dem Speicher erfolgt auch immer in Blöcken die ein Vielfaches von 8 Bit (1 Byte) sind.
Die Prozessoren werden nicht effektiver wenn Sie auf kleineren Datenstrukturen arbeiten müssen.
Noch schlimmer:
Wenn man 8 Boolean in ein einzelnes Byte stecken würde, könnte es sein, dass an acht Stellen mit den acht Variablen gleichzeitig gearbeitet werden müsste. 7 Ausführungseinheiten müssten dann immer auf die achte warten die gerade das entsprechende Byte in ihrem Register bearbeitet.
Platzverschwendung: Boolean werden nicht so häufig wie andere Typen verwendet. Es macht bei den heutigen Hauptspeichergrößen für die meissten Anwendungen keinen Unterschied beim Hauptspeicherverbrauch.

2.2.2 Komplexe Javatypen

2.2.2 Komplexe Javatypen

Diese Datentypen werden mit Hilfe von Javaklassen implementiert. Die so erzeugten Datenstrukturen sind Javaobjekte und haben einen anderen Lebenszyklus als primitive Typen die in einer Javaklasse oder einem Programmierblock benutzt werden.

Komplexe Datentypen (Javaklassen) haben einen variablegroßen Speicherplatzbedarf. Sie werden auf dem Javafreispeicher (Heap) angelegt.

Zeichenketten

Zeichenketten sind in Java kein vordefinierter primitiver Typ. Zeichenketten werden im Paket java.lang mit Hilfe der Klasse String implementiert. Die Klasse String kann jedoch ohne eine spezielle Deklaration wie ein primitiver Typ verwendet werden.

Zeichenketten (Strings) sind in Java nicht modifizierbar. Bei jeder Zuweisung wird eine neue Datenstruktur angelegt. Bei primitiven Typen werden die Werte an der gleichen Stelle überschrieben.

Aufzählungstypen

Aufzählungstypen sind seit JDK 5.0 Bestandteil der Sprache.

Definition
Aufzählungstypen
Aufzählungstypen in Java haben einen Wertebereich der aus einer geordneten Menge von Konstanten besteht. Der aktuelle Wert einer Variablen besteht aus einem der Aufzählungskonstanten

Aufzählungstypen können nur als Bestandteil einer Klasse deklariert werden. Sie können nicht wie die anderen Basistypen innerhalb eines Blocks deklariert werden. Die Syntax einer Deklaration in einer Klasse ist die Folgende:

Syntax eines Aufzählungstyps

Beispiel einer Deklaration in einer Klasse:

class  AufzaehlungsDemo {
   enum Kartenfarbe {KARO, HERZ, PIK, KREUZ}
   enum Wochentag {MONTAG, DIENSTAG, MITTWOCH, DONNERSTAG, FREITAG, SAMSTAG, SONNTAG}
}

Bei der Benutzung von Aufzählungstypen kann nur eine zuvor deklarierte Aufzählungskonstante benutzt werden.

Beispiel der Benutzung in einer Klassenmethode der zugehörigen Klasse:

Wochentag heute = Wochentag.MITTWOCH;
Kartenfarbe dame = Kartenfarbe.HERZ;

Aufzählungstypen wurden wie Referenzvariablen (die erst später vorgestellt werden) implementiert.

Referenzen

Referenztypen erlauben es auf andere Objekte zu referenzieren. Sie werden im Abschnitt 7 behandelt.

Übergroße Zahlen (Big Decimal)

Die Java BigDecimal Klassen erlauben das Rechnen mit einer beliebigen Präzision. BigDecimal Klassen werden im Rahmen dieser Einführung nicht behandelt.

Stefan Schneider Sat, 10/29/2011 - 14:48

2.2.3 Typkonversion bei Zuweisung verschiedener Typen

2.2.3 Typkonversion bei Zuweisung verschiedener Typen

Die Sprache Java und ihre (Lautzeitumgebung) sind typsicher. Typsicher bedeutet, dass bei Zuweisungen für Variablen der Typ der Variable und der zugewiesene Typ eines Wertes geprüft werden und nur sichere Zuweisungen erlaubt werden. Der Übersetzer (javac) erkennt dies schon beim Parsen (lesen) des Quellcodes und meldet dies als Fehler.

Beispiel: Der Wertebereich einer Variable vom Type short endet bei 65535. Der Typ int hat jedoch einen Wertebereich der bis 4294967295 reicht. Im folgenden Fall kann es also zu einem Überlauf kommen:

short a;
int b;
....
a = b;

Der Übersetzer wird einen Fehler melden, da es hier zu einem Überlauf/Unterlauf aufgrund der unterschiedlichen Wertebereiche kommen kann.

Die Zuweisungskompatibilität kann man als Teilmengen mit dem Symbol ⊃ darstellen. In Java gilt die folgenden Beziehung:

doublefloatlongintshort/char byte

  • Alle Zuweisungen von bytedouble sind erlaubt. Java führt hier eine implizite Konvertierung (impliziter Cast) durch, weil es eine sichere Operation ist.
  • Alle Zuweisung von double ➔ byte werden vom Übersetzer nicht akzeptiert.

Bei Berechnungen vor der Zuweisung kommen eventuell verschieden Typen in Operationen (z.Bsp.) Addition vor.

Hier verfährt Java nach der folgenden Regel:

  • Der jeweils kleinere Operandentyp wird vor der Operation in den größeren konvertiert.
  • Die Operanden werden jedoch zumindest in den Typ int konvertiert
  • Das Ergebnis hat den gleichen Typ wie die beiden Operanden (nach Konvertierung)

Explizite Typkonvertierungen(Casts)

Um Zuweisungen zwischen inkompatiblen Typen zu erzwingen kann man den Zieltyp in runden Klammern dem Ausdruck voran stellen. Diesen Operator nennt man Castoperator (cast im englischen: gießen, betonieren).

Beispiel

short a;
int b;
....
a = (short)b; 

Hiermit erzwingt man Operationen die unsicher sein können! Es kann zu Überläufen in Wertebereichen oder Präzisionsverlusten kommen kann. Der Entwickler übernimmt hier die Verantwortung und überstimmt den Übersetzer. Der Castoperator sollte daher nur wenn nötig eingesetzt werden.

Das Applet zur Rechten ist in der Lage einen beliebigen Ganzzahltypen auf einen beliebigen anderen Ganzzahltypen zu zuweisen.

Die Variable y enthält den Eingabewert. Den Typ von y kann man in der rechten Spalte wählen.

Der Wert von y wird mit Hilfe einer Typkonversion (Cast) auf x zugewiesen. Den Typ von x kann man links wählen.

Nach der Wahl der Typen und des Eingabewerts kann die Zuweisung mit dem "Enter" Button gestartet werden.

Fragen:

  • Was geschieht bei der Typkonversion mit negativen Werten (siehe rotes Vorzeichenbit)?
  • Was geschieht bei der Zuweisung von großen Typen auf kleine Typen? Was geschieht mit den Vorzeichen?
  • Was geschieht wenn Zeichen (Typ char) auf andere Typen zugewiesen werden?

Zum Testen bitte runterladen: BinaerCastApplet.jar

Starten Sie die Anwendung mit einem Doppelclick im Download Ordner oder öffen ein Terminal und führen den folgenden Befehl im Download Ordner aus:

java -jar BinaerCastApplet.jar

Es sollte ein Fenster erscheinen welches wie folgt aussieht: 

Screenshot BinearCastApplet

 

Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole

Stefan Schneider Sat, 10/29/2011 - 15:25

Anonymous (not verified)

Sun, 12/16/2012 - 13:33

Laut "double ⊃ float ⊃ long ⊃int ⊃ short/char ⊃ byte" ist die Zuweisungen von Long-Literalen auf eine Float-Variable vom Compiler akzeptiert. Aber kommt es hier nicht zu Genauigkeitsverlusten, da long 64 Bit Genauigkeit hat und float nur 32 Bit. Und wenn ja, wieso akzeptiert der Compiler das dann trotzdem?

Korrekte Beobachtung. Ein long Typ kann Werte noch ohne Rundungsfehler korrekt darstellen wo ein float Typ schon im Bereich >1 also 20, 21, 22 etc.

Das ganze ist (wahrscheinlich) erlaubt da

  1. das Zahlenintervall des Typs float größer als das des Typ long ist. Es gibt also keinen Überlauf an den Grenzen der Zahlenintervalle
  2. Wer mit dem Typ float arbeitet muss wissen, das hier immer gerundet werden kann.

Anonymous (not verified)

Sun, 12/16/2012 - 13:41

Wenn ich in dem Applett auf der linken Seite den Typ byte wähle und auf der rechten Seite den Typ int. Dann müsste doch oben eigentlich in blauer Schrift die Zuweisung "byte x=(byte) y" stehen, oder? Jedenfalls steht dort "byte x=(int) y"; das würde doch gar nicht funktionieren, denn dann würde ich ja immer noch ein Int-Literal einer Byte-Variablen zuweisen.

2.3 Operatoren und Ausdrücke

2.3 Operatoren und Ausdrücke

Ausdrücke

Ausdrücke in Java sind alles was einen Rückgabewert liefert:

  • Konstanten
  • Variablen
  • Methoden
  • Operatoren

Operatoren

Java verfügt über

  • unäre (einstellige, monadische) Operatoren
  • binäre (zweistellige, dyadische) Operatoren
  • einen dreistelligen (ternären, tryadischen) Operator (den Bedingungsoperator "_ ? _ : _")

 

Unäre Operatoren haben einen einzigen Operanden. Beispiele sind:

  • Vorzeichenoperator: -a
  • Postinkrement: a++
  • Negation: !a
Unärer Operator

 

Binäre Operatoren haben zwei Operanden. Beispiele sind:

  • Addition:  a + b
  • logischer Vergleich: a ==  b
Binaerer Operator

Arithmetische Operatoren

Die arithmetischen Operatoren können auf die folgenden Typen angewendet werden

  • byte
  • short
  • int
  • long
  • float
  • double
Zweistellige arithmetische Operatoren
Operator Beispiel Semantik
+ a + b Addition: Summe von a und b
- a - b Subtraktion: Differenz an a und b
* a * b Multiplikation: Produkt von a und b
/ a /  b Division: Quotient von a und b
% a % b Modulo: Rest einer ganzzahligen Division von a durch b

Die Division von Ganzzahlen ergibt immer ganzzahlige Ergebnisse!

Java arbeitet ohne eine Erkennung des Überlaufs der Wertebereiche. Der Entwickler muss selbst die entsprechenden Vorsichtsmaßnahmen ergreifen.

Weiterhin gibt es einstellige (unäre) arithmetische Operatoren

Unäre arithmetische Operatoren
Operator Beispiel Semantik
+ +a Der Wert von a bleibt erhalten (Idempotente Operation)
- -a Der Wert von a wird negiert
++

a++

++a

Postinkrement: Der Ausdruck behält ursprünglichen Wert . Der Wert von a wurde um 1 erhöht

Präinkrement: Der Wert von a wird um 1 erhöht und der Ausdruck erhält den erhöhten Wert von a

--

x--

--x

Postdekrement: Der Ausdruck behält ursprünglichen Wert . Der Wert von a wurde um 1 erniedrigt

Prädekrement: Der Wert von a wird um 1 erniedrigt und der Ausdruck erhält den verminderten Wert von a

Die folgen drei Anweisungen bewirken das gleiche:

a = a + 1;
a++;
++a;

Bei Inkrementen mit gleichzeitiger Zuweisung ergeben jedoch unterschiedliche Werte für den zugewiesenen Wert

Variante 1 Wert a Wert b Variante 2 Wert a Wert b

a = 10; b = 4;

b = a++;

10

11

4

10 (!)

a = 10; b = 4;

b = ++a;

10

11

4

11 (!)

Beispiel

Quellcode Konsolenausgabe
package s1.block2.skript;
public class PrePostFixTest {
    public static void main(String[] args) {
        int x = 10;
        int y = 100;
        System.out.println("x = " + x + "; y = " + y);
        x++;
        System.out.println("x++ results in " + x);
        ++x;
        System.out.println("++x results in " + x);
        System.out.println("Set x to 0 ");
        x=0;
        System.out.println("x = " + x + "; y = " + y);
        y=x++;
        System.out.println("y=x++ (Postfix)");
        System.out.println("x = " + x + "; y = " + y);
        y=++x;
        System.out.println("y=++x (Prefix)");
        System.out.println("x = " + x + "; y = " + y);
}
.
.
.
.
.
x = 10; y = 100
.
x++ results in 11
.
++x results in 12
Set x to 0
. 
x = 0; y = 100
.
y=x++ (Postfix)
x = 1; y = 0
.
y=++x (Prefix)
x = 2; y = 2
.

Arithmetik der Ganzzahlen

  • Alle Operationen auf Ganzzahlen ergeben wieder Ganzzahlen. Dies wird nicht unbedingt von der Division erwartet!
  • Versuche durch 0 (Null) zu dividieren lösen eine ArithmeticException Ausnahme aus.

Arithmetik der Fließkommazahlen

Bei der Arithmetik mit Fließkommazahlen werden im Gegensatz zu den Ganzzahlen Überläufe erkannt. Die Fließkommazahlen besitzen eine Reihe Konstanten:

Konstante Semantik
POSITIVE_INFINITY Positiv unendlich
NEGATIVE_INFINITY Negativ unendlich
MAX_VALUE Größter darstellbarer Wert
MIN_VALUE Kleinster darstellbarer Wert
NaN "Not a number" Dieser Wert ist ungleich zu allen anderen Werten im Wertebereich

 

Vergleichsoperatoren

Gleichheit bzw. Ungleichheit bezieht sich auf den Wert der Variablen x und y

Vergleichsoperatoren
Operator Beispiel Semantik (Bedeutung)
== x == y ist x gleich y ?
!= x != y ist x ungleich y ?
< x < y ist x kleiner als y ?
<= x <= y ist x kleiner oder gleich y ?
> x > y ist x größer als y ?
>= x >= y ist x größer oder gleich y ?

 

Logische Operatoren

Die logischen Operatoren wirken auf den Typ Boolean der nur den Wert wahr oder falsch kennt.

Logische Operatoren
Operator Beispiel Semantik (Bedeutung)
! !a Negation
& a & b Und
| a | b Oder (inklusiv)
^ a ^ b Entweder-Oder
&& a && b bedingt auswertendes Und
|| a || b bedingt auswertendes Oder

 

Bedingungsoperator

Der dreistellige (ternäre) Bedingungsoperator (Konditionaloperator) erlaubt eine Zuweisung von dem Ergebnis einer Bedingung abhängig zu machen. Er hat die Form:

<ausdruck1> ? <ausdruck2> : <ausdruck3>

ausdruck1 muss einen boolschen Wert ergeben. Wird ausdruck1 wahr, so wird ausdruck2 der entsprechenden Variable zugewiesen. Wird ausdruck1 unwahr, so wird der ausdruck3 zugewiesen

Hiermit kann man Zuweisungen wie die Folgende formulieren

int maximum;
int x = 1;
int y =2 ;
maximum = (x > y) ? x : y ;

Das Ergebnis ist 2, da y (=2) größer als x (=1) ist.

Bedingt auswertende logische && und || Operatoren

Die bedingt auswertenden Operatoren werten Terme nur soweit aus bis das Endergebnis fest steht. Dies macht sie sehr effizient.

Im Beispiel:

boolean a = ((1<3) || (4>5));

wird der Term (4>5) nicht mehr ausgewertet. Da (1<3) wahr ist, steht das Endergebnis schon fest.

Die bedingt auswertenden logischen Operatoren wendet man neben Ihrem Geschwindigkeitsvorteil auch gerne an um potentielle Fehler und Ausnahmen zu vermeiden.

Ein Beispiel hierfür ist:

if ((a>0) && (Math.sqrt(a)>2))

Die Wurzel wird nur ausgewertet wenn a größer als Null ist.

Vorsicht: Durch die bedingte Auswertung können unterschiedliche Ergebnisse enstehen wenn in einem Ausdruck gleichzeitig ein Wert verändert wird!

Beispiel:

  bedingter "Oder" Operator einfacher "Oder" Operator
Quellcode
public static void t1() {
   int a = 3;
   int b = 5;
   if ((a>1) || (a<b++)){
      System.out.println ("Hallo");
   }
   System.out.println("b= " + b);
}
public static void t2() {
   int a = 3;
   int b = 5;
   if ((a>1) | (a<b++)){
      System.out.println ("Hallo");
   }
   System.out.println("b= " + b);
}
Ausgabe
Hallo
b= 5
Hallo

b= 6

Das Postinkrement (b++) in der linkten bedingten oder Bedingung wird nicht ausgeführt, da der Ausdruck (a>1) schon wahr geworden ist.

Bitoperatoren

Mit Bitoperatoren werden alle Bits einer Variablen einzeln manipuliert.

Bitoperatoren
Operator Beispiel Bedeutung
~ ~a Komplement
& a & b Und
| a | b Oder
^ a ^b exklusives Oder

Beispiel

package s1.block2.skript;
public class BitOperator {
    public static void main(String[] args) {
        int a = 7;
        int b = 6;
        int result;

        result = a & b;
        System.out.println("a = " + a + "; b = " + b + " result = " + result);

        result = a | b;
        System.out.println("a = " + a + "; b = " + b + " result = " + result);

        result = a ^ b;
        System.out.println("a = " + a + "; b = " + b + " result = " + result);
    }
}

Ergebnis

a = 7; b = 6 result = 6
a = 7; b = 6 result = 7
a = 7; b = 6 result = 1

Erklärung

result = a & b
Variable Dezimal Binär
a 7 0 0000000 00000000 00000000 00000111
b 6 0 0000000 00000000 00000000 00000110
result = a & b 6 0 0000000 00000000 00000000 00000110
result = a | b
Variable Dezimal Binär
a 7 0 0000000 00000000 00000000 00000111
b 6 0 0000000 00000000 00000000 00000110
result = a | b 7 0 0000000 00000000 00000000 00000111

Bitschiebeoperatoren 

Bitschiebeoperatoren

Operator

Beispiel Bedeutung
<< a << b Wert des Ausdrucks sind die Bits von a die um b Positionen nach links verschoben wurden. Es wird mit 0 Bits aufgefüllt.
>> a >> b Wert des Ausdrucks sind die Bits von a  die um b Positionen nach rechts verschoben wurden. Es wird mit dem höchsten Bit aufgefüllt.
>>> a >>> b Wert des Ausdrucks sind die Bits von a die um b Positionen nach rechts verschoben wurden. Es wird mit dem "0" Bits aufgefüllt.

Das kleine Programm rechts erlaubt die drei Bitschiebeoperationen zu testen.

Es kann die Bits um jeweils eine Stelle verschieben.

Hier die jar Datei herunterladen.

Das Programm dann mit dem Kommandozeilenbefehl:

java -jar IntShiftApplet.jar

Es erscheint ein Fenster wie folgt:

 Bild des IntShiftApplet

Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole.

Beispiel

package s1.block2.skript;
public class ShiftingBits {
    public static void main(String[] args) {
        int x = 4;
        int result;
        int shift = 1;

        result = x << shift;
        System.out.println("x = " + x + "; shift = " + shift + " result = " + result);

        result = x >> shift;
        System.out.println("x = " + x + "; shift = " + shift + " result = " + result);

        result = result >> shift;
        System.out.println("x = " + x + "; shift = " + shift + " result = " + result);

        result = result >> shift;
        System.out.println("x = " + x + "; shift = " + shift + " result = " + result);

        result = result >> shift;
        System.out.println("x = " + x + "; shift = " + shift + " result = " + result);
    }
}

Ergebnis


 
x = 4; shift = 1 result = 8
x = 4; shift = 1 result = 2
x = 4; shift = 1 result = 1
x = 4; shift = 1 result = 0
x = 4; shift = 1 result = 0

Die interne Darstellung der verwendeten Werte:

Binäre Darstellung
Dezimalwert Binärwert
8 0 0000000 00000000 00000000 00001000
4 0 0000000 00000000 00000000 00000100
2 0 0000000 00000000 00000000 00000010
1 0 0000000 00000000 00000000 00000001
0 0 0000000 00000000 00000000 00000000

 

Zuweisungs- und Verbundoperatoren

Das Gleichzeichen = dient in Java als Zuweisungsoperator. Die Anweisung

x = y + z;

ist nicht als mathematische Gleichung zuverstehen, sondern als Zuweisung des Ausdrucks auf der echten Seite (y+z) auf die Variable x auf der linken Seite.

Zuweisungen wie:

x = y = 8;

sind auch möglich. Sie haben die gleiche Bedeutung wie

y = 8;
x = y;

Für die meisten binären Operatoren gibt es Verbundoperatoren mit denen man einer Variable etwas zuweisen kann und gleichzeitig den alten Wert verwenden kann:

Verbundoperator
Verbundoperator entspricht
a += b a = a + b
a -= b a = a - b
a *= b a = a * b
a /= b a = a / b
a %= b a = a % b
a &= b a = a & b
a |= b a = a | b
a ^= b a = a ^ b
a <<= b a = a << b
a >>= b a = a > b
a >>>= b a = a >>> b

 

Auswertungsreihenfolge

Für Ausdrücke mit mehreren Operatoren gelten die folgenden Regeln in Bezug auf die Reihenfolge der Auswertung:

  1. Teilausdrücke in runden Klammern werden wie in der Mathematik als erstes ausgewertet
  2. Ausdrücke mit unären Operatoren werden anschließend ausgewertet
  3. Zuletzt werden Teilausdrücke mit mehrstelligen Operatoren ausgewertet

Unäre Operatoren haben alle die gleiche Priorität

Ausführungsreihenfolge von Operatoren

Die Ausführungsreihenfolge von Operatoren bestimmt wie ein Term aufgelöst wir.

Tipp: Es ist guter Programmstil Terme übersichtlich zu gestalten. Verwenden Sie im Zweifelsfall Klammern!

Ausführungsreihenfolge von Operatoren
Rang Operator Beschreibung
1 =, +=, -=, *= ... Zuweisungsoperator
2 ?: Bedingungsoperator
3 || Logische Oder
4 && Logisches Und
5 | logisches oder bitweises Oder
6 ^ logisches oder bitweises Entweder-Oder
7 & logisches oder bitweises Und
8 ==, != Vergleichsoperatoren: Gleich, Ungleich
9 <, <=, >, >= Vergleichsoperatoren
10 <<, >>, >>> Schiebeoperatoren
11 +, - Addition, Subtraktion, Verketten von Zeichenketten
12 *, /, % Multiplikation, Division, Rest
13 ++, --, +, -, ~, ! unäre (einstellige) Operatoren

 Auswertung von Operatoren mit gleicher Priorität

Es kann vorkommen, dass ein Ausdruck mehrere Operatoren der gleichen Priorität besitzt. In diesen Fällen wird die Auswertereihenreihenfolge durch die Assoziativität der Operatoren bestimmt.

Definition
Operatorenasoziativität
Die Assoziativität von Operatoren ist die Reihenfolge in der Operanden durch Operatoren gleicher Priorität verknüpft werden

Ist ein Operator linksassoziativ, wird zuerst der linke Operand ausgewertet. Das Beispiel zeigt den Plus- und Minusoperator. Beide haben die gleiche Priorität. Hier wird zuerst der Operand a+b ausgewertet.

linksassoziative Operanden

Einige Operatoren in Java sind rechtsassoziativ. Ein Beispiel hierfür ist der Zuweisungsoperator

Bewertungsreihenfolge der Operanden eines Operators

Definition
Bewertungsreihenfolge der Operanden
In Java werden die Operanden eines Operators strikt von links nach rechts ausgewertet.

Diese Regel ist insbesondere wichtig, da Methoden und diverse Operatoren Nebeneffekte haben können. Das bedeutet, dass diese Operatoren den Wert von Variablen während der Auswertung des Gesamtausdrucks verändern. Beispiele sind die Inkrement- und Dekrementoperatoren.

j = i-- -i;

ist ein zulässiger Ausdruck in Java.  Der Wert der j zugewiesen wird ist immer 1;

Die Auswertung dieser Zuweisung geschieht in den folgenden Schritten:

  1. Auswertung des Subtrahenden (und Zwischenspeicherung)
  2. Dekrement von i
  3. Auswertung des Minuend und Berechnung der Differenz
  4. Zuweisung der Differenz auf j

Ein Beispielprogramm zum Testen:

package s1.block2.skript;
public class PrePostInkrement {
    public static void main(String[] args) {
        int i = 4;
        int j;
        
        j=i-- -i;
        System.out.println("i: " +i+", j= "+j);
    } 
}

Ausgabe:

i: 3, j= 1

Die Auswertung des Ausdrucks und der Zuweisung j= i-- -i; findet wie folgt statt:

i j j= i-- -i; Kommentar
4 0 j = 4 - i; Bestimmung des Minuend der Subtraktion
3 0 j = 4 - i; Postdekrement von i
3 0 j = 4 -3; Bestimmung des Subtrahend der Subtraktion
3 0 j = 1; Bestimmung der Differenz
3 1   Zuweisung

Regeln für den Ergebnistyp von arithmetischen Ausdrücken (Widening Conversions)

Java kann alle arithmetischen Operationen auch ausführen wenn die Zahlentypen im Ausdruck unterschiedlich sind. Das Ergebnis der Berechnung hängt von den Typen des Ausdrucks ab. Es gilt in der folgenden Reihenfolge:

  1. Ist einer der Typen ein double, so wird das Ergebnis zum Typ double konvertiert.
  2. Falls nicht, wird das Ergebnis zu einem float Typen konvertiert wenn ein Typ ein float Typ ist.
  3. Falls nicht, wird das Ergebnis zu einem long Typen konvertiert wenn ein Typ ein long Typ ist.
  4. Falls nicht, werden beide Operanden zuerst zu einem int Typen konvertiert.

 

Stefan Schneider Tue, 07/06/2010 - 09:48

Stefan Schneider

Sun, 12/16/2012 - 14:54

In reply to by Anonymous (not verified)

Danke. Ich habe den Fehler korrigiert.

Anonymous (not verified)

Sun, 12/16/2012 - 13:53

Sie schreiben, dass "x=y=8;" die gleiche Bedeutung hat wie "x=8; y=8;". Dabei wird doch x der Wert von y zugewiesen und nicht direkt die Zahl 8, oder? Also müsste "x=y=8;" äquivalent sein mit "y=8; x=y" (da ja die Ausdrücke von rechts nach links ausgewertet werden). Oder?

Sie haben sehr, sehr wahrscheinlich recht.

Man müsste sich zur finalen Klärung den generierten Bytecode anschauen oder im Debugger zwischen die beiden Zuweisungen kommen.

Der folgende Javacode ist ein starkes Indiz, dass Sie recht haben:

int x,y;
x = y = 8;
//(x = y) = 8; // So etwas geht nicht
x = (y = 8); // So etwas geht. Diese Klammer ist an dieser Stelle wahrscheinlich redundant. y wird hier garantiert vorher belegt.
x = (y = 8)+1; // So etwas geht auch. Damit wird das Prinzip auf die Spitze getrieben. x erhält jetzt den Wert 9.
System.out.println(x);
System.out.println(y);

Hane den Text nach Ihrem Vorschlag geändert.

Anonymous (not verified)

Wed, 01/16/2013 - 13:35

DHBW-Mannheim - Java Vorlesung - hier sind wir gerade oder ??
Wer guckt alles und findet den comment???

___________c$$$$$$$$$$$$$$$$$$$$$$$$$$h,
________c$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
____d$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
____$$$,d$$$$$$$$$$$$$$$$$$$$$$$$$hc`?$$$$
___$$$u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$h,?$$
___$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$b$$$
___$$$$$P$$?$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
___$$$$$$$`$$$$$$$$$$$$$$$$$$$$$$$$$d$$$$$$
____$$$$$$c ,nn,?$$$$$$$$$$$$$$$,,`$$$$$$$$
_____$$ MMMMM`$$$$$$$$$$$$F,MMMb`$$$$$$$$
______$$$MMTTM.?$$$$$$$$$$$,MMM $$$$$$$$
_______`$$$$$,M;;;`$$$$$$$$$$´M,,`,$$$$$$
__________?$$$$, ____________?$$$$,( ) $$$$$$$$$$ (´ ),$$$
____________`$$$$.`-´ $$$$$$$$$$,`--´,$$$´
____________$$$$$hh$$$$$????$$$hc$$$$$$$´
___________d$$$$$$$$$ `======´ $$$$$$$;
___________ $$$$$$$$$$$$c,,,,c$$$$$$$$$
____________?$$$$P $$$$$$?????$$??$$$$
______________________$$$$$
_____________________4$$$$$c
____________________,$$$$$$$
__________________z$ ________________> z$ _________________ ________________`$ _________________?L$$$$$$$$$$$:$
__________________?$$$$$$$$$$$d´
___________________`$$$$$$$$$$F
____________________`?$c`??3$F
____________________CCC_CCC
____________________,;CC_CC;;
____________________`CC__CCC
.,,,,,CCCCCCCCCCCCCCC__CCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCC__CCCCCCC,CCCCCCCCCCC
CCCCCCCCCCCCCCCCCC___CCCCC´`´CCCCCCCCCC

Anonymous (not verified)

Tue, 01/22/2013 - 16:39

public class PrePostInkrement {
public static void main(String[] args) {
int i = 4;
int j;

j=i-- -i;
System.out.println("i: " +i+", j= "+j);
}
}

Müsste hier für j nicht 0 rauskommen? Und i = 3?
Der Operator -- (also i--;) findet doch erst nach der Zuweisung statt oder?

Stefan Schneider

Tue, 01/22/2013 - 20:22

In reply to by Anonymous (not verified)

Ich habe den genauen Ablauf in das Skript eingebaut.
Das Dekrement findet statt nachdem der Minuend bestimmt worden ist.
Das bedeutet, das Dekrement findet nach der Zuweisung des Minuenden statt. Nicht nach der Zuweisung auf j!
Die Zuweisung des Minuenden kann man als Zuweisung auf eine temporäre Variable verstehen.

Anonymous (not verified)

Fri, 10/11/2019 - 11:24

Bei den unären arithmetischen Operatoren steht "Präidekrement" statt "Prädekrement".

Hallo,

der ternäre Operator ist ja rechtsassoziativ.

Weshalb ergibt der folgende Ausdruck dann " a größer b"?

int a = 10;
int b = 5;

String r = a > b ? "a größer b" : a < b ? "a kleiner b" : "beide gleich";
System.out.println( r );

Es müsste doch eigentlich erst a < b ausgewertet werden, oder?

2.4 Übungen

2.4 Übungen

Duke als Boxer

2.4.1 Übung: Zuweisungen und Typen 

Erstellen Sie folgende Java-Applikation (Name "Calc"):
  • Deklarieren Sie in der main() Routine Variablen mit unterschiedlichen Datentypen (z.B. int, longshort, float).
  • Initialisieren Sie die Variablen mit geeigneten Werten.
  • Führen Sie mit den Variablen folgende arithmetischen Operationen aus:
    • Addition einer Konstanten zu einer int-Variablen,
    • Multiplikation einer int-Variablen mit einer Konstanten,
    • Subtraktion zweier Variablen unterschiedlichen Datentyps (int, short),
    • Division einer int-Variablen durch eine Konstante,
    • Multiplikation zweier Variablen (davon eine vom Typ "float").
Geben Sie die Variablenwerte jeweils aus.
Zu beantworten:
  • Wie groß sind die Wertebereiche der einzelnen Typen?
  • Was geschieht wenn man zwei Ganzzahlen (int) dividiert und das Ergebnis ist keine ganze Zahl?
  • Was geschieht wenn Sie einen Überlauf in einem Wertebereich einer Variablen provozieren?

Beispiellösung

2.4.2 Übung: Erlaubte Variablennamen

Welche der folgenden Symbole sind gültige Variablennamen in Java?
Begründen Sie Ihre Antwort.
maxvalue
maxValue
max_value
max value
end
End
10%ofSum
sum10
_10PercentOfSum

2.4.3 Übung: Literale

Warum übersetzt das folgende Programm nicht?

package block2;
public class Literale {
    public static void main(String[] args) {
        long i1 = 4000000000;
        long i2 = 4000000000L;
        System.out.println(i1);
        System.out.println(i2);
    }
}

2.4.4 Übung: Ausdrücke

Gegeben seien folgende Variablendeklarationen in Java:

long a = 3;
int b = 4;
short c = 5;
byte d = 6;

Welchen Wert liefern die folgenden Ausdrücke und von welchem Typ sind sie?

d / b * a
c + b * (d + 1)
d / (c - 1) * b / 2
d % b
-c % b

2.4.5 Übung: Zuweisungen

Gegeben seien folgende Variablendeklarationen in Java:
long a = 3;
int b = 4;
short c = 5;
byte d = 6;
Welche der folgenden Zuweisungen sind in Java erlaubt?
a = b + 3 * (d + 1);
b = c * c;
c = b / 3;
d = (byte)a + b;
d = (byte) ( a + b);

2.4.6 Übung: Ausdrücke

Schreiben Sie einen Java-Ausdruck, der eine ganze Zahl x auf das nächstliegende Vielfache von 100 rundet.

Beispiel:

  • der Wert 149 soll auf 100 abgerundet werden
  • der Wert 150 auf 200 aufgerundet werden.

2.4.7 Übung: Zeitrechnung

Schreiben Sie ein Java-Programm, das eine Anzahl von Sekunden einliest und in
die Anzahl von Stunden, Minuten und Sekunden umrechnet.
Testen Sie Ihr Programm mit vernünftigen Eingabewerten, z. B. mit 0, 59, 60,
100, 3600 und 4000.
 
Beispiel: Die Eingabe 1234 soll zur Ausgabe von 0 : 20 : 34 führen.

2.4.8 Übung: Polynomberechnung

Schreiben Sie ein Javaprogramm, das die Koeffizienten a, b, c, d sowie den Wert x des Polynoms
y = a * x3  + b * x2  + c * x + d
einliest und das Ergebnis y ausgibt.

2.4.9 Übung: Abstand zwischen Punkten

Schreiben Sie ein Java-Programm, das die x- und y-Koordinaten zweier Punkte einliest und den Abstand zwischen ihnen berechnet und ausgibt.

Tipp: Math.sqrt() berechnet eine Wurzel

2.4.10 Übung: Berechnung von ∏ (Pi) 

Die Kreiszahl ∏ kann durch folgende Näherungsformel berechnet werden:

             i  
 ∏    n  (-1)          1     1     1     1 
--- = ∑ ------- = 1 - --- + --- - --- + --- - ... 
 4   i=0 2*i+1         3     5     7     9
Schreiben Sie ein Java-Progamm, das ∏ mit dieser Formel annähert.
Bemerkung: Die Reihe konvergiert nur seht langsam gegen ∏ .

2.4.11 Übung: Analoge Uhr

Implementieren sie notwendigen Berechnungen zum Anzeigen von Sekunden-, Minuten, Stundenzeigern einer analogen Uhr.

Vorbereitungen

  1. Erzeugen Sie in einem Verzeichnis die beiden Quelldateien Uhr.java und Zeiger.java. Der Quellcode der beiden Dateien ist weiter unten aufgeführt.
  2. Übersetzen Sie die beiden Dateien in diesem Verzeichnis mit dem Befehl javac Uhr.java Zeiger.java
  3. Führen Sie das Programm aus: java Uhr
  4. Beobachten Sie den blauen Sekundenzeiger. Er wächst in jeder Sekunde um ein Pixel nach rechts unten

Aufgabe

Implementieren Sie die korrekte Position der Spitze der drei Zeiger abhängig von der aktuellen Zeit in der Klasse Zeiger.java

Die korrekte Spitze wird durch eine x und y Koordinate beschrieben. Der Ursprung des Koordinatensystems liegt in der Mitte der Uhr. Postive X-Koordinaten reichen nach rechts. Positive Y-Koordinaten reichen nach unten. Die Richtung der Y-Koordinaten ist typisch für für Java GUIs in Swing oder AWT.

Hinweis: Implementieren Sie zuerst den Sekundenzeiger. Er erlaubt ihnen binnen 60 Sekunden die visuelle Kontrolle Ihrer Programmierung. Die Programmierung der Minutenzeiger und Stundenzeiger sind dann sehr einfach, da sie auf der gleichen mathematischen Formel basieren.

Empfohlendes Vorgehen:

  1. Erstellen Sie die mathematische Formel für die aktuelle Spitze des Sekundezeigers abhängig von der Sekunde zwischen 0 und 59. Sie benötigen hierzu die Sinus- und Cosinusfunktion sowie die Konstante PI
  2. Finden sie in der Klasse Zeiger.java die Methoden sekundeX und sekundeY
  3. Ersetzen Sie in der Trivialimplementierung die Zuweisung xs=s; bzw ys=s; durch die korrekte Implementierung der beiden mathematischen Ausdrücke
  4. Sichern Sie die Datei Zeiger.java
  5. Übersetzen Sie die Datei Zeiger.java
  6. Testen Sie das Ergebnis mit dem Kommando: java Uhr
  7. Wiederholen Sie Schritt 3-6 bis Sie das gewünschte Ergebnis haben.
  8. Implementieren Sie den Minuten und Stundenzeiger sinngemäß.

Beispiele der Ausgangssituation und der korrekten Implementierung: 

Ausgangssituation Ziel der Übung
analoge Uhr, initial Zustand Analoge Uhr als Lösung nit korrekten Zeigern

Tipps

  • maxRadius: Diese Konstante der Klasse Zeiger gibt die maximale (vernünftige) Zeigergröße vor.
    • Nutzen Sie diesen Wert für einen großen regulären Sekundenzeiger
    • Skalieren Sie die Minuten- und Stundenzeiger relativ zu dieser Größe (z. Bsp. maxRadius*4/5 )
  • die Mathematikbibliothek wurde statisch importiert. Sie können direkt die benötigen trigonometrischen Operation und Konstanten benutzen:
  • Beachten Sie die Eingabe- und Ausgabeparameter der trigonometrischen Funktionen! Die Berechnungen erfolgen mit Fließkommazahlen. Das Ergebnis muss aber eine ganzzahlige Pixelposition sein.
  • Ganzzahloperation runden immer ab. Erwägen Sie die Benutzung einer Fließkommahilfsvariable
  • Benutzen nur double als Fließkommatyp. Die Operationen der Mathematikbibliothek beruhen auf dem Typ double. Sie vermeiden so unnötige Konvertierungen zu float Typen.

Klasse Uhr

/*
 * Zeichnen einer analogen Uhr in einem JFrame
 */
import java.awt.*;
import java.awt.event.*;

import java.util.Calendar;
import javax.swing.*;

/**
*
* @author sschneid
*/
public class Uhr extends JPanel {

   static int sekunde = 0;
   static int minute = 0;
   static int stunde = 0;
   static String tzString; // aktuelle Zeitzone
   static int initialHeight;
   static float zoom = 1;

   /**
   * Hauptprogramm der Anwendung. Es werden keine Eingabeparameter benötigt
   * @param args dieser Parameter wird nicht ausgewertet
   */
   public static void main(String[] args) {
      JFrame hf; // Das Fenster der Anwendung
      hf = new JFrame("Uhr");
      // Beenden der Anwendung bei Schliesen des Fenster
      hf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      Uhr dieUhr = new Uhr();
      // Aufbau des Contentpanes
      Container myPane = hf.getContentPane();
      myPane.add(dieUhr, BorderLayout.CENTER);

      // Erzeuge einen Menüeintrag zum Beenden des Programms
      JMenuBar jmb = new JMenuBar();
      JMenu jm = new JMenu("Datei");
      JMenuItem exitItem = new JMenuItem("Beenden");
      exitItem.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            System.exit(0);
         }
      });
      jm.add(exitItem);
      jmb.add(jm);
      hf.setJMenuBar(jmb);

      hf.pack();
      // Das JFrame sichtbar machen
      // Gewünschte Größe setzen
      // 1. Parameter: horizontale Größe in Pixel
      // 2. Parameter: vertikale Größe in Pixel
      hf.setSize((int)(2 * Zeiger.maxRadius*zoom + 80),
         (int)(2 * Zeiger.maxRadius*zoom + 80));
      hf.setVisible(true);
      hf.setAlwaysOnTop(true);
      // Initialgröße merken. Entspricht Zoomfaktor 1
      dieUhr.initialHeight = dieUhr.getHeight();
      // Update von Panel in zyklischen Intervallen
      try {
         while (true) {
            Thread.sleep(500); // Schlafe x Millisekunden
            // Hole Systemzeit und belege statische Variablen
            Calendar call = Calendar.getInstance();
            tzString = call.getTimeZone().getDisplayName();
            sekunde = call.get(Calendar.SECOND);
            minute = call.get(Calendar.MINUTE);
            stunde = call.get(Calendar.HOUR);
            dieUhr.repaint();
        }
      } catch (InterruptedException e) {
      System.out.println(
         "Die Anwendung wird wegen einer Ausnahme beendet");
      }
   }
   /**
   * Überladene Paintmethode. Sie führt alle Zeichenoperationen im Panel aus
   * @param g vom Laufzeitsystem übergebenes Graphikobjekt.
   */
   @Override
   public void paint(Graphics g) {
      super.paint(g);
      zoom = (float)getHeight()/(float)initialHeight;
      int maxRadius = Zeiger.maxRadius;
      int xCenter = (int)(maxRadius*zoom) + 40;
      int yCenter = (int)(maxRadius*zoom) + 20;
      float fontSize = g.getFont().getSize2D();

      int charCenterOffSet = (int)(fontSize/2);
      String timeString = stunde + ":" + minute + ":" + sekunde
            + " " + tzString;
      // Zeichne Uhrenhintergrung und Koordinatensystem
      g.setFont(g.getFont().deriveFont(fontSize));
      g.setColor(Color.WHITE); // Farbe
      g.fillArc((int)(xCenter - maxRadius*zoom),
         (int)(yCenter - maxRadius*zoom),
         (int)(maxRadius*zoom*2),
         (int)(maxRadius*zoom*2), 0, 360);
      g.setColor(Color.BLACK); // Farbe
      g.fillArc((int)(xCenter - 3*zoom), (int)(yCenter - 3*zoom),
         (int)(10*zoom), (int)(10*zoom), 0, 360);

      g.drawLine(xCenter, yCenter, (int)(xCenter + 40*zoom), yCenter);
      g.drawLine(xCenter, yCenter, xCenter, (int)(yCenter + 40*zoom));
      g.drawString("X", (int)(xCenter + 45*zoom),
         yCenter + +charCenterOffSet);
      g.drawString("Y", xCenter - charCenterOffSet,
         (int)(yCenter + 55*zoom));
      g.drawString("12",xCenter - charCenterOffSet,
         (int)(yCenter - maxRadius*zoom));
      g.drawString("3", (int)(xCenter + maxRadius*zoom),
         yCenter + charCenterOffSet);
      g.drawString("6", xCenter - charCenterOffSet,
         (int)(yCenter + 2*charCenterOffSet+maxRadius*zoom));
      g.drawString("9", (int)(xCenter - maxRadius*zoom - charCenterOffSet),
         yCenter + charCenterOffSet);
      // Zeichne aktuelle Zeit zum Debuggen
      g.drawString(timeString, 0,
         (int)(yCenter + maxRadius*zoom));

      // Zeichne Stundenzeiger
      g.setColor(Color.BLACK);
      g.drawLine(xCenter, yCenter,
         (int)(xCenter + Zeiger.stundeX(stunde)*zoom),
         (int)(yCenter + Zeiger.stundeY(stunde)*zoom));
      g.drawString("h["
         + Zeiger.stundeX(stunde)
         + "," + Zeiger.stundeY(stunde) + "]",
         0, (int)(yCenter + maxRadius*zoom - (3*fontSize)));
      // Zeichne Minutenzeiger
         g.setColor(Color.RED);
         g.drawLine(xCenter, yCenter,
            (int)(xCenter + Zeiger.minuteX(minute)*zoom),
            (int)(yCenter + Zeiger.minuteY(minute)*zoom));
         g.drawString("m["
            + Zeiger.minuteX(minute) + ","
            + Zeiger.minuteY(minute) + "]", 0,
            (int)(yCenter + maxRadius*zoom - (2*fontSize)));
            // Zeichne Sekundenzeiger
         g.setColor(Color.BLUE);
         g.drawLine(xCenter, yCenter,
            (int)(xCenter + Zeiger.sekundeX(sekunde)*zoom),
            (int)(yCenter + Zeiger.sekundeY(sekunde)*zoom-fontSize));
         g.drawString("s["
            + Zeiger.sekundeX(sekunde) + ","
            + Zeiger.sekundeY(sekunde) + "]", 0,
            (int)(yCenter + maxRadius*zoom - fontSize));
   }
}

Klasse Zeiger

Implementieren sie

import static java.lang.Math.*;

/**
*
* @author sschneid
*/
public class Zeiger {
   public static final int maxRadius = 100; // Beeinflusst GUI-Größe !

   /**
   * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle X Koordinate der Zeigerspitze des Sekundenzeigers
   * auf dem Bildschirm
   */
   public static int sekundeX(int s) {
      int xs;
      /* Implementierung Beginn */
      xs = s; // Proformazuweisung. Sie ist zu ersetzen
      /* Implementierung Ende */
      return xs;
   }

   /**
   * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle Y Koordinate der Zeigerspitze des Sekundenzeigers
   * auf dem Bildschirm
   */
   public static int sekundeY(int s) {
      int ys;
      /* Implementierung Beginn */
      ys = s; // Proformazuweisung. Sie ist zu ersetzen
      /* Implementierung Ende */
   return ys;
   }

   /**
   * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle X Koordinate der Zeigerspitze des Minutenzeigers
   * auf dem Bildschirm
   */
   public static int minuteX(int m) {
      int xm;
      /* Implementierung Beginn */
      xm = m; // Proformazuweisung. Sie ist zu ersetzen
      /* Implementierung Ende */
     return xm;
   }

   /**
   * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle Y Koordinate der Zeigerspitze des Minutenzeigers
   * auf dem Bildschirm
   */
   public static int minuteY(int m) {
      int ym;
      /* Implementierung Beginn */
      ym = m; // Proformazuweisung. Sie ist zu ersetzen
      /* Implementierung Ende */
      return ym;
   }

   /**
   * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12
   * @return aktuelle X Koordinate der Zeigerspitze des Stundenzeigers
   * auf dem Bildschirm
   */
   public static int stundeX(int h) {
      int xh;
      /* Implementierung Beginn */
      xh = h; // Proformazuweisung. Sie ist zu ersetzen
      /* Implementierung Ende */
      return xh;
   }

   /**
   * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12
   * @return aktuelle Y Koordinate der Zeigerspitze des Stundenzeigers
   * auf dem Bildschirm
   */
   public static int stundeY(int h) {
      int yh;
      /* Implementierung Beginn */
      yh = h; // Proformazuweisung. Sie ist zu ersetzen
      /* Implementierung Ende */
     return yh;
  }
}

Hilfestellung

Hier nicht weiterlesen, wenn Sie einfache trigonometrische Aufgaben lösen können!

max-Zeit ist bei Sekunden 60, bei Minuten 60, bei Stunden 12

Die X-Koordinate eines Zeigers berechnet sich wie folgt

x-Koordinate: Sinus(aktuelle-Zeit/max-Zeit*2*PI)*zeiger-länge-in-pixel

Die Y-Koordinate eines Zeigers berechnet sich wie folgt

Y-Koordinate: -Cosinus(aktuelle-Zeit/max-Zeit*2*PI)*zeiger-länge-in-pixel

Beachten Sie, dass in Java das Kommutativgesetz nicht vollständig gilt. Der Typ und die Auswertereihenfolge spielen auch eine Rolle!

2.4.12 Gruppenübung

Je eine Gruppe bearbeitet die folgenden Typen:

  • short
  • char
  • int
  • long
  • float
  • double

Jede Gruppe trägt die folgenden Aspekte eines Typs in 5 Minuten vor

  • Schlüsselwort des Typ
  • Anzahl der verwendeten Bits
  • Wertebreich 
    • Grenzen mit Konstanten dazu
    • Echte Obermengen oder Untermengen der anderen Typen nennen
    • Beispiel für die Benutzung dieses Types. Das Beispiel sollte nicht optimal für die anderen Typen sein!
  • Syntax der Literale um Werte zuzuweisen
  • Programmierbeispiele
    • Syntax der Literale benutzen und vorstellen
    • Typische Operation und Zuweisung
    • mehrere interessante Operationen und Zuweisungen die zu Sonderfällen bzw. Extremfällen führen

Zeitvorgaben

  • Selbst lesen: 5 Minuten
  • Teamdiskussion: 10 Minuten
  • Beispiel Programmieren: 20 Minuten
  • Zusammenfassung, Abstimmung Vortrag: 5 Minuten

 2.4.13 Airline

Vorbereitung

  • Legen Sie ein neues Paker Block2 an
  • Nutzen Sie die neue Klasse Flughafen
  • Kopieren Sie die Klasse Flugzeug aus dem Block1 in den Block2

Aufgabe:

  • Legen Sie in der Klasse Flugzeug die folgenden Attribute als öffentliche (public) Attribute an. Wählen Sie einen passenden Typen
    • passagiere
    • besatzung
    • treibstoff
    • leergewicht
    • maxGewicht
  • Legen Sie zwei statische Variablen an in der Form
    • static final int durchschnittsGewicht= 75;
    • static final double kerosinGweicht= 0.796; // kg/dm3
  • Kopieren der Methoden (siehe unten) in die Klasse Flugzeug
    • gewicht()
    • toString()
    • drucken()
  • Implementieren der Methode gewicht()
    • Deklarieren Sie eine Variable
    • berechnen Sie das aktuelle Gesamtgewicht
    • geben Sie diese Variable zurück. Ersetzen Sie die 0 in return durch Ihre Variable
  • Erweitern Sie die Klasse Flughafen
    • Nutzen Sie das Objekt auf das lh1 zeigt.
    • Belegen Sie alle Attribute mit vernünftigen Werten
    • Rufen Sie die Methode drucken() für lh1 auf.
    • Kontrollieren Sie die Werte
  • Testen Sie das Programm in der Klasse Flugzeug
  • In der Klasse Flugzeug
    • Entnehmen Sie dem Treibstofflager des Flughafen 2000 Liter Treibstoff und füllen Sie Ihn in das Flugzeug lh1

Klasse Flugzeug

Im block2 anlegen!

package Airline.block2;

/**
*
* @author stsch
*/
public class Flugzeug {
String kennzeichen;

/**
*
* @return aktuelles Gewicht;
*/
public double gewicht() {
// Berechnen Sie das aktuelle Gewicht:
// 1. Anlegen einer Variablen
// 2. Berechnen des Gewichts
// 3. Variable in return zurückgeben
return 0;
}

public String toString() {return kennzeichen;}

public void drucken() {
System.out.println("Objekt: " + this);
System.out.println("kennzeichen: " + kennzeichen);
System.out.println("passagiere: " + passagiere);
System.out.println("Besatzung: " + besatzung);
System.out.println("Treibstoff: " + treibstoff);
System.out.println("Leergewicht: " + leergewicht);
System.out.println("maxGewicht: " + maxGewicht);
System.out.println("aktuelles Gewicht: " + gewicht());
}
}

Klasse Flughafen

package Airline.block2;


 

package Airline.block2;

/**
*
* @author stsch
*/
public class Flughafen {
String name;
Flugzeug gate1;
Flugzeug gate2;
Flugzeug gate3;
Flugzeug gate4;
Flugzeug gate5;
Flugzeug gate6;
double treibstoffLager;

public static void main(String[] args) {
Flughafen pad = new Flughafen();

pad.name = "Paderborn";
pad.treibstoffLager = 1000000;
// Boeing 747, https://de.wikipedia.org/wiki/Boeing_747#747-400
Flugzeug lh1 = new Flugzeug();
lh1.kennzeichen ="D-ABTL";

pad.gate1 = lh1;

System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");

pad.gate1=null;
pad.gate2=lh1;

System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");

}
}

 

Stefan Schneider Sun, 06/20/2010 - 14:56

2.5 Lösungen

2.5 Lösungen

2.5.1 Zuweisungen und Typen 

class ArithmeticTest {
  public static void main (String args[]) {
    short x = 6;
    int y = 4;
    float a = 12.5f;
    float b = 7f;
    System.out.println("x is " + x + ", y is " + y);
    System.out.println("x + y = " + (x + y));
    System.out.println("x - y = " + (x - y));
    /* ??? */
    System.out.println("x % y = " + (x % y));
    System.out.println("a is " + a + ", b is " + b);
    /* ??? */
  }
}

2.5.2 Erlaubte Variablennamen

siehe Spezifikation Java 7 (Identifier)

Lösung durch Testen mit javac

public class VariableNames {   
   int maxvalue;
   int maxValue;
   int max_value;
   //int max value;
   int end;
   int End;
   //int 10%ofSum;
   int sum10;
   int _10PercentOfSum;
  public static void main(String[] args) {
  }
}

Erklärung

  • maxvalue: korrekter Name
  • maxValue: korrekter Name
  • max_value: korrekter Name
  • max value: Leerstelle im Namen ist nicht erlaubt
  • end: korrekter Name
  • End: korrekter Name
  • 10%ofSum: Ziffer als erstes Zeichen ist nicht erlaubt
  • sum10: korrekter Name
  • _10PercentOfSum: korrekter Name

2.5.3 Literale

Das Programm übersetzt nicht weil

  • der Wert 4000000000 ein "Integer"-Literal ist
  • der Wert 4000000000 den Wertebereich einer Ganzzahl vom Typ "Integer" übersteigt
  • Die Zuweisung auf eine Variable vom Typ "Long" spielt zu diesem Zeitpunkt noch keine Rolle

2.5.4 Ausdrücke

public class Expressions {
    
    public static void main(String[] args) {
      long a = 3;
      int b = 4;
      short c = 5;
      byte d = 6;
      
      int  result1;
      long result2;

      result2 = d / b * a;
      System.out.println("d / b * a = " + result2 );

      result1 = c + b * (d + 1);
      System.out.println("c + b * (d + 1) = " + result1 );

      result1 = d / (c - 1) * b / 2;
      System.out.println("d / (c - 1) * b / 2 = " + result1 );

      result1 = d % b;
      System.out.println("d % b = " + result1 );

      result1 = -c % b;
      System.out.println("-c % b = " + result1 );
    }

}

Ergebnis

d / b * a = 3
c + b * (d + 1) = 33
d / (c - 1) * b / 2 = 2
d % b = 2
-c % b = -1

2.5.5 Zuweisungen

public class AllowedAssigments {

    public static void main(String[] args) {
        long a = 3;
        int b = 4;
        short c = 5;
        byte d = 6;

        a = b + 3 * (d + 1);
        b = c * c;
        c = (byte)(b / 3);
        d = (byte)(((byte)a + b));
        d = (byte) ( a + b);
    }

}

2.5.6 Ausdrücke

public class Runden {

    public static void main(String[] args) {
        int a, result;
        
        a =149;
        result = (a +50)/100*100;
        System.out.println("Eingabe = " + a + " Ergebnis = " + result);

        a =150;
        result = (a +50)/100*100;
        System.out.println("Eingabe = " + a + " Ergebnis = " + result);
    }
}

Ergebnis

Eingabe = 149 Ergebnis = 100
Eingabe = 150 Ergebnis = 200

2.5.7 Zeitrechnung

public class timeCalculation {

    public static void main(String[] args) {
        int a,h,m,s;

        a = 0;
        h = a/3600;
        m = (a-h*3600)/60;
        s = a - h*3600 - m*60;
        System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s);

        a = 59;
        h = a/3600;
        m = (a-h*3600)/60;
        s = a - h*3600 - m*60;
        System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s);

        a = 60;
        h = a/3600;
        m = (a-h*3600)/60;
        s = a - h*3600 - m*60;
        System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s);

        a = 100;
        h = a/3600;
        m = (a-h*3600)/60;
        s = a - h*3600 - m*60;
        System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s);

        a = 3600;
        h = a/3600;
        m = (a-h*3600)/60;
        s = a - h*3600 - m*60;
        System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s);

        a = 4000;
        h = a/3600;
        m = (a-h*3600)/60;
        s = a - h*3600 - m*60;
        System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s);
    }

}

Ergebnis

Sekunden = 0 = 0:0:0
Sekunden = 59 = 0:0:59
Sekunden = 60 = 0:1:0
Sekunden = 100 = 0:1:40
Sekunden = 3600 = 1:0:0
Sekunden = 4000 = 1:6:40

2.5.8 Polynomberechnung

public class Polynom {
    public static void main(String[] args) {
        double a, b, c, d, x, y;

        a =  1.2;
        b = -2.3;
        c =  4.5;
        d = -6.7;

        x = 8.9;

        y = a*x*x*x+b*x*x+c*x+d;
        System.out.print("Ergebnis = "+ y);
        System.out.println("\n oder...");

        y = a*Math.pow(x,3)+b*Math.pow(x,2)+c*x+d;
        System.out.print("Ergebnis = "+ y);
    }
}

Ergebnis

Ergebnis = 697.1298
 oder...
Ergebnis = 697.1297999999999

2.5.9 Abstand zwischen Punkten

public class Main {
    public static void main(String[] args) {
       double x1,x2, y1, y2, x, y, d;

       x1 = 1; y1 = 1;
       x2 = 4; y2 = 5;

       x = x1-x2;
       y = y1-y2;
       d = Math.sqrt(x*x+y*y);
       System.out.println("distance = " + d);
    }
}

Ergebnis

distance = 5.0

2.5.10 Berechnung von ∏ (Pi)

Hilfe; Java Spezifikation: Division

public class PiCalculation {

    public static void main(String[] args) {
        double pi;

        pi = (1.0 - 1.0/3.0 + 1.0/5.0 - 1.0/7.0 + 1.0/9.0 - 1.0/11.0 + 1.0/13.0)*4;
        System.out.println("Pi = "+ pi);
        System.out.println("\n oder ...");

        pi=1;
        for (int i=1;i<=10000;i++) {
            pi = pi + Math.pow(-1,i)/(2*i+1);
        }
        pi=pi*4;
        System.out.println("Pi = "+ pi);

    }

Ergebnis

Pi = 3.2837384837384844

 oder ...
Pi = 3.1416926435905346

2.5.11 Analoge Uhr

import static java.lang.Math.*;
/**
*
* @author stsch
*/
public class Zeiger {
   public static final int maxRadius = 100; // Beeinflusst GUI-Größe !
   /**
   * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle X Koordinate der Zeigerspitze des Sekundenzeigers
   * auf dem Bildschirm
   */
   public static int sekundeX(int s) {
      int xs;
      /* Implementierung Beginn */
      double sx = sin(s*2*PI/60)*maxRadius;
      xs = (int)sx;
      /* Implementierung Ende */
      return xs;
   }
   /**
   * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle Y Koordinate der Zeigerspitze des Sekundenzeigers
   * auf dem Bildschirm
   */
   public static int sekundeY(int s) {
      int ys;
      /* Implementierung Beginn */
      double sy = -cos(s*2*PI/60)*maxRadius;
      ys = (int)sy;
      /* Implementierung Ende */
      return ys;
   }
   /**
   * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle X Koordinate der Zeigerspitze des Minutenzeigers
   * auf dem Bildschirm
   */
   public static int minuteX(int m) {
      int xm;
      /* Implementierung Beginn */
      double mx = sin(m*2*PI/60)*maxRadius*0.75;
      xm = (int)mx;
     /* Implementierung Ende */
     return xm;
   }
   /**
   * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59
   * @return aktuelle Y Koordinate der Zeigerspitze des Minutenzeigers
   * auf dem Bildschirm
   */
   public static int minuteY(int m) {
      int ym;
      /* Implementierung Beginn */
      double my = -cos(m*2*PI/60)*maxRadius*0.75;
     ym = (int) my;
     /* Implementierung Ende */
     return ym;
   }
   /**
   * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12
   * @return aktuelle X Koordinate der Zeigerspitze des Stundenzeigers
   * auf dem Bildschirm
   */
   public static int stundeX(int h) {
      int xh;
      /* Implementierung Beginn */
      double hx = sin(h*2*PI/12)*maxRadius*0.5;
      xh = (int)hx;
     /* Implementierung Ende */
     return xh;
   }
   /**
   * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12
   * @return aktuelle Y Koordinate der Zeigerspitze des Stundenzeigers
   * auf dem Bildschirm
   */
   public static int stundeY(int h) {
      int yh;
      /* Implementierung Beginn */
      double hy = -cos(h*2*PI/12)*maxRadius*0.5;
      yh = (int)hy;
      /* Implementierung Ende */
      return yh;
   }
}

 2.5.13 Airlines

Klasse Flughafen

package Airline.Block2;

/**
*
* @author stsch
*/
public class Flughafen {
String name;
Flugzeug gate1;
Flugzeug gate2;
Flugzeug gate3;
Flugzeug gate4;
Flugzeug gate5;
Flugzeug gate6;
double treibstoffLager;

public static void main(String[] args) {
Flughafen pad = new Flughafen();

pad.name = "Paderborn";
pad.treibstoffLager = 1000000;
// Boeing 747, https://de.wikipedia.org/wiki/Boeing_747#747-400
Flugzeug lh1 = new Flugzeug();
lh1.kennzeichen ="D-ABTL";

pad.gate1 = lh1;

System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");

pad.gate1=null;
pad.gate2=lh1;

System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");

lh1.leergewicht = 184567;
lh1.maxGewicht = 412770;
lh1.passagiere = 200;
lh1.besatzung = 10;

lh1.drucken();

}
}

Klasse Flugzeug

package Airline.Block2;

/*

*
* @author stsch
*/
public class Flugzeug {
String kennzeichen;
static final int durchschnittsGewicht= 75;
static final double kerosinGweicht= 0.796; // kg/dm3
public int passagiere;
public int besatzung;
public double treibstoff;
public double leergewicht;
public double maxGewicht;

/**
*
* @return aktuelles Gewicht;
*/
public double gewicht() {
// Berechnen Sie das aktuelle Gewicht:
// 1. Anlegen einer Variablen
// 2. Berechnen des Gewichts
// 3. Variable in return zurückgeben
double meinGewicht = leergewicht + passagiere*durchschnittsgewicht+
besatzung*durchschnittsgewicht+treibstoff*gewichtKerosin;

return meinGewicht;
}

public String toString() {return kennzeichen;}

public void drucken() {
System.out.println("Objekt: " + this);
System.out.println("kennzeichen: " + kennzeichen);
System.out.println("passagiere: " + passagiere);
System.out.println("Besatzung: " + besatzung);
System.out.println("Treibstoff: " + treibstoff);
System.out.println("Leergewicht: " + leergewicht);
System.out.println("maxGewicht: " + maxGewicht);
System.out.println("aktuelles Gewicht: " + gewicht());
}
}

 

Stefan Schneider Sun, 06/20/2010 - 15:58

2.6 Webcast: Java Variablen, Zuweisungen und Operatoren

2.6 Webcast: Java Variablen, Zuweisungen und Operatoren

Ein graphisch animierter Webcast der die genauen Vorgänge des folgenden Beispielprogramms erläutert:

public class Mitarbeiter {
...
   public static void main (String[] args) {
      int a;
      long b;
      String eingabe;
      eingabe = args[0];
      a = 15;
      a++;
      b = 2*a;
      System.out.println("Ausgabe :" + eingabe + b);
   }
}

Das folgende Video dauert 8 Minuten.

Wichtige Aspekte:

  • genaue Lebensdauer von Variablen
  • genaues Vorgehen bei einem Cast
  • Verwalten von temporären Datenstrukturen
Stefan Schneider Fri, 10/29/2010 - 15:48

Anonymous (not verified)

Wed, 03/20/2013 - 12:21

Sind mitarbeiterID und name nicht Objektattribute? Klassenattribute werden doch normalerweise mit static implementiert?

Richtig beobachtet. Das Beispiel ist insofern unglücklich, als das es nichts von der Klasse Mitarbeiter nutzt.

2.7 Fragen

2.7 Fragen

Duke grübelt

2.7.1 Ganzzahlarithmetik

Ganzzahloperationen haben eine Reihe von Eigenheiten. Es wird auf eine Variable a eine Variable b zugewiesen die um 25% größer sein soll. Hierfür gibt es drei Möglichkeiten. Im ersten Fall sei a klein (=6). Welches ist die beste Implementierung? Welche Operationen sind heikel?

  Implementierung Ergebnis

.
.
a.)
b.)
c.)

int a = 0;
int b = 6;
a = b*5/4;
a = b/4*5;
a = b*(5/4);
 

 Was ist die beste Implementierung wenn man weiß das b groß ist? Z.Bsp. b= 230? Welche Operation ist heikel?

2.7.2 Sichere Zuweisungen

Welche der folgenden Zuweisungen sind sicher b.z.w unsicher?

Eine Zuweisung sei unsicher wenn bei der Zuweisung abhängig von der gewählten Variablenbelegung Datenverluster auftreten können.

Analysieren Sie die sechs Zuweisungen auf potentielle Datenverluste. Die Werte von a_short, b_int, c_long wurden absichtlich am oberen Ende des jeweiligen Wertebereichs gewählt um den Präzisionsverlust zu provozieren.

Hinweis: Vergleichen Sie die Wertebereiche der Ausgangs und Zielvariablen.

Ignorieren Sie die Auswertelogik. Das Programm ist ausführbar. Es wird die Belegungen der einzelnen Variablen auf der Konsole drucken. Es wird bei jedem Fall von Präzisionsverlust einen Text "(Fehler)" hinter die Ausgabe anfügen.

public class UebungTypkonversion {

public static void main(String[] args) {
// Alle Werte sind der drittgrößte Wert des jeweiligen Wertebereichs
short a_short = Short.MAX_VALUE-2; // short = 16 bit
int b_int = Integer.MAX_VALUE-2; // int = 32 bit
long c_long = Long.MAX_VALUE-2; // long = 64 bit

// cast auf float: Welche Zuweisungen können zu Präzisionsverlusten führen?
float c_float = a_short;
float d_float = b_int;
float e_float = c_long;

// cast auf double:Welche Zuweisungen können zu Präzisionsverlusten führen?
double f_double = a_short;
double g_double = b_int;
double h_double = c_long;

// Auswertelogik und Kontrolle
System.out.println("a_short=" + a_short);
System.out.println("a_int=" + b_int);
System.out.println("a_long=" + c_long);
System.out.print("short auf float= " + c_float + " ");

// Sind die Werte nach der Rückkonvertierung noch gleich?
if (a_short == (short)c_float) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("int auf float= " + d_float);
if (b_int == (int)d_float) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("long auf float= " + e_float);
if (c_long == (long)e_float) {System.out.println("(OK)");}
else { System.out.println("(Fehler)");}

System.out.print("short auf double= " + f_double + " ");
if (a_short == (short)f_double) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("int auf double= " + g_double);
if (b_int == (int)g_double) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("long auf double= " + h_double);
if (c_long == (long)e_float) {System.out.println("(OK)");}
else { System.out.println("(Fehler)");}

}
}

 

Stefan Schneider Mon, 02/28/2011 - 17:14

2.8 Antworten

2.8 Antworten

2.8.1 Ganzzahlarithmetik

Bei Ganzzahldivisionen werden alle Ergebnisse abgerundet.

Option a.) ist hier die optimale Lösung da der Rundungsfehler relativ gesehen am kleinsten ist wenn man zuerst multipliziert um dann eine möglichst große Zahl zu teilen.

Option c.) ist schlecht, da da 5/4 schon innerhalb der Klammer auf 1 abgerundet wird.

Option b.) ist ebenfalls schlecht da 6/4 ebenfalls auf 1 abgerundet wird

  Implementierung Ergebnis

.
.
a.)
b.)
c.)

int a = 0;
int b = 6;
a = b*5/4;
a = b/4*5;
a = b*(5/4);
.
.
a=7
a=5
a=6 

Die Variable b ist sehr groß b= 230:

  • Option b.) ist vorteilhaft.
  • Hier wird die Multiplikation zum Risiko. Der maximale 32 Bit Ganzzahlwert (231-1) kann bei Option a.) und b.) überschritten werden. Der Überlauf wird vom Laufzeitsystem nicht gemeldet und das Ergebnis ist falsch da negativ. Ein Überlauf des Wertebereichs durch die Mutiplkation ist wahrscheinlich schlimmer als ein Rundungsfehler durch eine frühe Division.

2.8.2 Sichere Zuweisungen

Konsolenausgaben:

a_short=32765
a_int=2147483645
a_long=9223372036854775805
short auf float= 32765.0 (OK)
int auf float= 2.14748365E9(Fehler)
long auf float= 9.223372E18(Fehler)
short auf double= 32765.0 (OK)
int auf double= 2.147483645E9(OK)
long auf double= 9.223372036854776E18(Fehler)

Die Mantisse des Typ float ist nicht groß genug um extrem große (oder kleine) Werte des Typs int und long präzise zu verwalten.

Die Mantisse des Typ double ist nicht groß genug, um extrem große (oder kleine) Werte des Typs long präzise zu verwalten.

 

Stefan Schneider Tue, 03/01/2011 - 08:28

2.9 Lernziele

2.9 Lernziele

Am Ende dieses Blocks können Sie:

  • ....die Begriffe Schlüsselwort, Variable, Zuweisung, Typ, Literal, Operator im Javakontext erkennen, unterscheiden, erklären und anwenden.
  • ...Javaschlüsselworte erkennen und etwa 30 nennen (Dieses Lernziel soll erst am Ende der ersten Vorlesung erreicht sein)
  • ...erlaubte Namen in Java und Schlüsselworte unterscheiden.
  • ...den Unterschied zwichen Literalen und Namen erklären.
  • ...drei Arten von Kommentaren benutzen.
  • ...die unterschiedlichen primitiven Datentypen kennen und Ihren Werte aus dem Format herleiten.
  • ...wichtige Unterschiede in der Ganzzahlarithmetik und der Fließkommaarithmetik erklären
  • ...sichere von unsicheren Zuweisungen unterscheiden
  • ...erklären warum String kein primitiver Datentyp ist
  • ...ein Beispiel für einen Aufzählungstyp nennen
  • ...die Notwendigkeit von expliziten Typkonversionen nennen und das damit verbundene Risiko abschätzen
  • ...je einen unären, einen binären und einen ternären Operator nennen
  • ...die Auswertereihenfolge eines Terms beschreiben
  • ...mit Post- und Präinkrementoperatoren umgehen

Lernzielkontrolle

Sie sind in der Lage die folgenden Fragen zu Typen, Operationen und Zuweisungen zu beantworten.

Interessante Fragen aus den Übungen:

Feedback

Zur Umfrage

QR Code für Umfrage

Stefan Schneider Thu, 08/16/2012 - 16:34

Anonymous (not verified)

Sun, 11/23/2014 - 14:08

Was genau meinen Sie mit "...wichtige Unterschiede in der Ganzzahlarithmetik und der Fließkommaarithmetik erklären"? Können Sie dies bitte etwas genauer erläutern?

lG

Stefan Schneider

Sun, 11/23/2014 - 16:00

In reply to by Anonymous (not verified)

 Ganzzahlarithmetik:

  • extrem schnell
  • präzise bei Addition, Subtraktion, Multiplikation solange das Ergebnis im Wertebereich bleibt
  • keine Fehlermeldungen beim Überschreiten des Wertebereichs
  • Javaausnahme nur bei der Division durch Null.

Fließkommanarithmetik

  • schnell auf modernen 64 Bitprozessoren
  • Alle Operationen sind mehr oder weniger ungenau. Dies hängt von der Größe der Mantisse und des Exponenten ab.
  • Besondere Zustände wie "Infinity" oder "Not a number"
  • Javaausnahmen beim Überschreiten der Wertbereiche.