1. Gleitkommazahlen
Angenommen, Sie möchten einen einfachen Taschenrechner schreiben. Oder irgendein anderes Programm, in dem gerechnet wird (vom banalen Geldzählen bis zur komplexen Physik). In der realen Welt ist längst nicht alles eine ganze Zahl – und damit müssen wir umgehen!
Also rüsten wir uns mit einem neuen Datentyp aus!
In der Programmierung werden Bruchzahlen auch reelle Zahlen oder Gleitkommazahlen (floating-point) genannt. In Java, wie in den meisten Sprachen, dienen sie dazu, nicht nur ganze, sondern auch „gebrochene“ Werte zu speichern: allerlei 3.14, -28.57, 2.718281828...
Gleitkommazahlen gibt es in zwei Haupttypen:
| Typ | Speichert | Wertebereich (ungefähr) | Genauigkeit | Typische Größe |
|---|---|---|---|---|
|
Zahlen | ±1.5 × 10-45 ... ±3.4 × 1038 | ~7 signifikante Stellen | 4 Byte |
|
Zahlen | ±5.0 × 10-324 ... ±1.7 × 10308 | ~15–16 signifikante Stellen | 8 Byte |
Typ float
Der Typ float hat seinen Namen von floating-point number – Zahl mit gleitendem Dezimalpunkt. Reelle Zahlen stammen aus der Mathematik und haben bestimmte Eigenschaften. Ein Computer hat jedoch viele Einschränkungen. Daher ist es nicht ganz korrekt, Bruchzahlen in Java „reelle Zahlen“ zu nennen. Stattdessen spricht man von „Gleitkommazahlen“.
Der Typ float speichert üblicherweise 7 signifikante Ziffern (z. B. 0.1234567), einen Zehnerexponenten und belegt 4 Byte im Speicher. Das ist für präzise Berechnungen sehr wenig, daher wechselte man schnell zu Zahlen doppelter Genauigkeit.
Typ double
Der Typ double hat seinen Namen von doppelter (double) Genauigkeit. Er belegt im Speicher 8 Byte (2-mal so groß wie float) und kann bis zu 15 signifikante Ziffern speichern: 0.123456789012345. Das reicht für die meisten Berechnungen mit Bruchzahlen völlig aus, weshalb double in Java der Standardtyp zur Speicherung von Gleitkommazahlen ist.
In dieser Vorlesung liegt der Schwerpunkt auf dem Typ double: Er wird standardmäßig für alle „gewöhnlichen“ Gleitkommazahlen empfohlen. Später betrachten wir auch den Typ float.
2. Deklaration und Initialisierung von Variablen des Typs double
Alles wie bei int – nur verwenden wir jetzt double.
// Variable deklarieren und ihr den Wert von Pi zuweisen
double pi = 3.1415926;
// Man kann auch ohne Initialisierung deklarieren
double averageSalary;
averageSalary = 91234.56;
// Man kann rechnen!
double pizzaPieces = 8;
double friends = 3;
double piecesPerFriend = pizzaPieces / friends; // 2.666... (und nicht 2)
Besonderheiten der Syntax:
- Als Dezimaltrennzeichen wird der Punkt verwendet (3.14). Wenn Sie ein Komma verwenden, erhalten Sie einen Kompilierungsfehler!
- Streng genommen erhalten Sie bei double d = 3; keinen Fehler – die Typen werden automatisch konvertiert (eine Ganzzahl wird verlustfrei zu einer „Gleitkommazahl“).
3. Eingabe und Ausgabe von Gleitkommazahlen mit Scanner
Probieren wir zuerst, eine Gleitkommazahl auszugeben:
double amount = 42.75;
System.out.println(amount); // Gibt aus: 42.75
Alles gut! Und wenn wir Text hinzufügen:
System.out.println("Auf Ihrem Konto: " + amount + " Euro."); // Auf Ihrem Konto: 42.75 Euro.
Eingabe über die Tastatur
Für die Eingabe eines double verwenden Sie die spezielle Methode der Klasse Scanner: console.nextDouble().
Scanner console = new Scanner(System.in);
System.out.println("Geben Sie die Temperatur draußen ein:");
double temperature = console.nextDouble(); // Wir lesen direkt ein double ein
System.out.println("Draußen ist es jetzt: " + temperature + " Grad.");
4. Der Typ double in Aktion: Arithmetik
Alle gewohnten Operationen (+, -, *, /) funktionieren genauso wie bei int:
double distance = 100.5;
double time = 2.0;
double speed = distance / time; // 50.25
System.out.println("Durchschnittsgeschwindigkeit: " + speed); // Durchschnittsgeschwindigkeit: 50.25
Das ist die ganze Arithmetik. Der einzige Unterschied: Das Ergebnis einer Division ist immer eine Gleitkommazahl, wenn mindestens einer der Operanden double ist.
Vergleich mit int
int a = 5, b = 2;
System.out.println(a / b); // 2 (Rest wird verworfen)
double aa = 5, bb = 2;
System.out.println(aa / bb); // 2.5
5. Typische Fehler und Merkwürdigkeiten im Umgang mit double
Fehler bei der Umwandlung der Eingabe
Die klassische Situation: Der Benutzer gibt 3,14 ein – das Programm erwartet aber 3.14. In Java richtet sich die Methode Scanner.nextDouble() nach der aktuellen Locale: In russischer/deutscher Locale ist das Komma zulässig, in der englischen ist ein Punkt erforderlich. Bei Bedarf stellen Sie die Locale für Scanner ein oder lesen die Zeile ein und parsen manuell.
// Das verursacht in Locale.US ein Problem, wenn "3,14" eingegeben wird
double value = console.nextDouble();
„Ungenauigkeit“ von Zahlen im Computer
Hier beginnt bei Einsteigern oft leichte Verwunderung:
double x = 0.1 + 0.2;
System.out.println(x); // Hm... 0.30000000000000004
Glückwunsch, Sie sind auf die „Magie“ der internen Darstellung von Gleitkommazahlen gestoßen. Viele Zahlen lassen sich im Binärsystem nicht exakt darstellen. Das ist für die meisten Anwendungen unkritisch, hat aber Tücken in Finanzen und exakten Wissenschaften.
6. Wichtig: double und int – automatische und explizite Umwandlung
Es kommt vor, dass Sie eine ganze und eine gebrochene Zahl addieren oder einen int einer double-Variablen zuweisen – das führt zu keinem Fehler:
int i = 2;
double d = i; // Alles ok!
System.out.println(d); // 2
double dd = 3.7;
int ii = (int) dd; // Den Typ double explizit in int umwandeln!
System.out.println(ii); // 3 – der Nachkommateil wurde verworfen
Das führt oft zu Überraschungen – warum ist der Nachkommateil nach dem Cast verschwunden? Einfach weil der Typ int keine Nachkommastellen speichern kann (alles, was nach dem Punkt steht, ist dauerhaft weg).
Mehr über die Umwandlung von double in int und den Operator (int) in der nächsten Vorlesung.
7. Formatierte Ausgabe: double schön ausgeben
Oft wird ein double standardmäßig mit vielen überflüssigen Nullen ausgegeben. Man kann die Ausgabe formatieren:
double temp = 23.56789;
System.out.println(temp); // 23.56789
// 2 Nachkommastellen
System.out.println(String.format("%.2f", temp)); // 23.57
// 1 Nachkommastelle
System.out.println(String.format("%.1f%n", temp)); // 23.6
| Format | Ergebnis | Beschreibung |
|---|---|---|
|
23.57 | Zahl mit 2 Nachkommastellen |
|
23.6 | Zahl mit 1 Nachkommastelle |
8. Typische Fehler im Umgang mit float und double
Fehler Nr. 1: implizite Umwandlung von double in float
float f = 1.23; // Fehler!
Der Compiler wird sich beschweren: „Sie versuchen, ein double in ein float zu stecken – das kann zu Genauigkeitsverlust führen!“ Fügen Sie immer das Suffix f hinzu.
Fehler Nr. 2: Vergessen, dass die Division zweier int ein int-Ergebnis liefert
int a = 7, b = 2;
double result = a / b; // 3.0 statt 3.5
Um den Nachkommateil zu erhalten, wandeln Sie mindestens einen Operanden explizit um:
double result = (double) a / b; // 3.5
Fehler Nr. 3: Vergleich von Gleitkommazahlen
Vergleichen Sie Gleitkommazahlen nicht mit == auf Gleichheit. Verwenden Sie einen Vergleich mit einer kleinen Toleranz (Epsilon).
Fehler Nr. 4: Genauigkeitsverlust bei float
Speichern Sie keine großen Zahlen oder sehr präzisen Werte in float – sie können „kaputtgehen“ oder wichtige Ziffern verlieren.
GO TO FULL VERSION