Variablen (2)
Ein bisschen Mathematik
Kommen wir noch einmal zurück auf das Thema Zahlen.
Auf der vorletzten Seite haben Sie gelernt, dass Java streng zwischen
Ganzzahlen und Kommazahlen unterscheidet. Das führt manchmal zu
Ergebnissen, die auf den ersten Blick verwundern.
Was meinen Sie, was das folgende Programm ausgibt?
Erst nachdenken, dann ausprobieren, dann erst unten weiterlesen, bitte!
public class Division {
public static void main(String[] args) {
System.out.println(5/3);
}
}
Java interpretiert 5 und 3 als Integerzahlen und
dividiert 5 / 3 = 1. Es berechnet also keine Nachkommastellen.
Wenn Sie wollen, können Sie sich aber mit dem Term 5%3
den Rest berechnen lassen:
Probieren Sie folgende Zeile: System.out.println("5 durch 3 ist " + 5/3 + " Rest " +5%3);
Was aber, wenn Sie das Ergebnis mit Nachkommstellen angezeigt bekommen möchten? Dann haben Sie zwei Möglichkeiten:
Entweder, Sie schreiben die 5 als Kommazahl:
System.out.println(5.0/3);
Oder Sie teilen Java mit, dass die 5 als Kommazahl
gemeint ist: System.out.println((double)5/3);
Die zweite Methode nennt man einen Typecast. Sie hilft manchmal aus kniffligen Situationen. Betrachten Sie das folgende Beispiel:
import java.util.*;
public class Gauß {
public static void main(String[] args) {
int n, summe;
Scanner Eingabe = new Scanner(System.in);
System.out.println("Summe der Zahlen von 1 bis n nach Gauß");
System.out.println(); // erzeugt eine Leerzeile
System.out.print("Geben Sie die Obergrenze n ein :");
n = Eingabe.nextInt();
summe=(1+n)*(n/2);
System.out.println("Die Summe aller Zahlen von 1 bis "+n+"
ist "+summe);
}
}
Der Mathematiker Carl Friedrich Gauß (1777-1855) soll in jungen Jahren, als ihn sein Lehrer damit ärgern wollte, dass er ihn alle Zahlen von 1 bis 100 zusammenzählen ließ, kombiniert haben: 1+100=101, 2+99=101, 3+98=101,... Wenn ich also die erste und die letzte Zahl zusammenzähle und mit der Anzahl aller Zahlenpaare, also in diesem Fall mit der Hälfte der letzten Zahl multipliziere, dann habe ich weniger Arbeit. Kurz: 1 + 2 + 3 + ... + n = (1+n) * (n/2).
Diese Methode verwendet auch unser Programm. Auf den ersten Blick ist alles in Ordnung. Die Summe der Zahlen von 1 bis 10 wird korrekt mit 55 berechnet. Geben Sie jedoch die Obergrenze mit 9 an, dann gibt das Programm die Summe 40 aus (statt des korrekten Ergebnisses 45). Der Grund ist, dass n als ganze Zahl deklariert ist. Der Term n/2 liefert also bei uns 9 ganzzahldividiert durch 2. Das aber ist 4 und nicht 4,5.
Ändern Sie die Formel in summe=(int)((1+n)*((double) n/2)); und die Rechnung geht auf. Was ist da passiert?
Durch das Voranstellen von (float) wurde n in eine Kommazahl umgewandelt. Diese liefert, bei Division durch 2 das Ergebnis 4,5.
Das Gesamtergebnis des Terms ist (1+9)*4,5 = 45,0 also ebenfalls eine Kommazahl. Um die aber in der Integervariablen summe zu speichern, muss sie erst wieder in eine Integerzahl verwandelt werden. Dazu setzen wir den ganzen Term in Klammern und stellen ihm den Typecast (int) voran.
Mach's rund
Wir hätten den Term auch noch auf anderem Weg passend machen können: summe = Math.rint((1+n)*((double)n/2));
In der Java Standardbibliothek gibt es eine Klasse Math. Diese enthält einige Methoden, die beim Umgang mit Zahlen nützlich sind. Sobald Sie den Namen einer Klasse aus der Standardbibliothek oder einer importierten Bibliothek eingeben, zeigt Ihnen der Java-Editor an, welche Methoden diese Klasse zur Verfügung stellt. Tippen Sie im Java-Editor Math. ein und blättern Sie durch die angebotenen Methoden:
Sie finden zwei Methoden, um Zahlen zu runden: Die rint()-Methode wandelt double-Werte in integer-Werte, die round()-Methode wandelt wahlweise float-Werte in integer-Werte (einfache Genauigkeit) oder double-Werte in long-Werte (doppelte Genauigkeit). Alle drei Methoden runden kaufmännisch je nach der ersten abgeschnittenen Stelle auf oder ab. Der oben erwähnte Typecast (int) dagegen schneidet die Nachkommastellen einfach weg. (Näheres hier.)
Darüber hinaus gibt es noch die floor()-Methode, mit der man zu einem double-Parameter die nächstkleinere und die ceil()-Methode mit der man die nächst größere ganze Zahl ermitteln kann.
PS: Wir hätten in der Gauß-Formel natürlich auch einfach die zweite Klammer weglassen können, dann hätte der Term bei jeder Eingabe korrekt funktioniert (Wieso eigentlich?). Aber dann hätten wir weder Typecast noch Math-Klasse kennen gelernt.
Wohin mit den vielen Kommastellen?
Eine ärgerliche Eigenschaft von Double-Zahlen ist, dass sie immer mit einem Haufen Nachkommastellen ausgegeben werden, auch wenn diese für den Nutzer völlig uninteressant sind. Sie können die Anzahl der Nachkommastellen einer ausgegebenen zahl selbst bestimmen, wenn Sie die println()-Methode durch die format()-Methode ersetzen:
System.out.format("Aus %8.2f Euro werden bei %3.1f Prozent nach %2.0f Jahren %8.2f Euro",k0,p,i,kn);
In den Ausgabestring werden Formatangaben eingebaut, die mit einem Prozentzeichen eingeleitet und mit dem Buchstaben f für Fließkommazahl abgeschlossen werden. Die Zahl nach dem Prozentzeichen bezeichnet vor dem Punkt die Anzahl der insgesamt reservierten Stellen und nach dem Punkt die Zahl der erwünschten Nachkommastellen. Nach dem Ausgabestring folgt ein Komma und dann werden der Reihe nach die Namen der Variablen aufgezählt, deren Inhalt für die Formatstrings eingebaut werden soll.
(Unser Beispiel bezieht sich auf Aufgabe 2 und setzt die Existenz der Double-Variablen k0, p, i und kn voraus.)
Aufgaben: