5.4 Die Eigenschaften der Klasse Math 

Die Klasse java.lang.Math ist eine typische Utility-Klasse, die nur statische Funktionen (beziehungsweise Attribute als Konstanten) deklariert. Mit dem privaten Konstruktor lassen sich (so leicht) keine Exemplare von Math erzeugen.
5.4.1 Attribute 

Die Math-Klasse besitzt zwei statische Attribute:
class java.lang.Math |
- static final double E
Die Eulersche Zahl [Die irrationale Zahl e ist nach dem schweizerischen Mathematiker Leonhard Euler (1707–1783) benannt.] e = 2.7182818284590452354.
- static final double PI
Die Kreiszahl Pi = 3.14159265358979323846. [Wer noch auf der Suche nach einer völlig unsinnigen Information ist: Die einmilliardste Stelle hinter dem Komma von Pi ist eine Neun.]
5.4.2 Absolutwerte und Maximum/Minimum 

Die abs()-Funktionen liefern den Betrag des Arguments (mathematische Betragsfunktion: y = |x|). Sollte ein negativer Wert als Argument übergeben werden, wandelt ihn abs() in einen positiven Wert um.
class java.lang.Math |
- static int abs( int x ), static long abs( long x )
- static float abs( float x ), static double abs( double x )
Hinweis Es gibt genau einen Wert, auf den Math.abs(int) keine positive Rückgabe liefern kann: –2147483648. Dies ist die kleinste darstellbare int-Zahl (Integer.MIN_VALUE), während +2147483648 gar nicht in ein int passt! Die größte darstellbare int-Zahl ist 2147483647 (Integer.MAX_VALUE). Was sollte abs(-2147483648) auch ergeben? |
Die max()-Funktionen liefern den größeren der übergebenen Werte. Die min()-Funktionen liefern den kleineren von zwei Werten als Rückgabewert.
class java.lang.Math |
- static int max( int x, int y ), static long max( long x, long y )
- static float max( float x, float y ), static double max( double x, double y )
- static int min( int x, int y ), static long min( long x, long y )
- static float min( float x, float y ), static double min( double x, double y )
5.4.3 Winkelfunktionen 

Die Math-Klasse stellt einige Winkelfunktionen und ihre Umkehrungen zur Verfügung. Im Gegensatz zur bekannten Schulmathematik werden die Winkel für sin(), cos(), tan() im Bogenmaß (2 * Pi entspricht einem Vollkreis) und nicht im Gradmaß (360 Grad entspricht einem Vollkreis) übergeben.
class java.lang.Math |
- static double sin( double x )
Liefert den Sinus von x.
- static double cos( double x )
Liefert den Kosinus von x.
- static double tan( double x )
Liefert den Tangens von x.
Die Arcus-Funktionen sind die Umkehrfunktionen zu den trigonometrischen Funktionen. Das Argument ist kein Winkel, sondern zum Beispiel bei asin() der Sinuswert zwischen –1 und 1. Das Ergebnis ist dann ein Winkel im Bogenmaß, etwa zwischen –Pi/2 und Pi/2.
class java.lang.Math |
- static double asin( double x )
- static double acos( double x )
- static double atan( double x )
Liefert den Arcus-Sinus/Arcus-Kosinus/Arcus-Tangens von x.
- static atan2( double x, double y )
Liefert bei der Konvertierung von Rechteckkoordinaten in Polarkoordinaten den Winkel theta, also eine Komponente des Polarkoordinaten-Tupels. Die Funktion berücksichtigt das Vorzeichen der Parameter x und y, und der freie Schenkel des Winkels befindet sich im richtigen Quadranten.
Hyperbolicus-Funktionen bietet Java über sinh(), tanh() und cosh().
Zur Umwandlung eines Winkels von Gradmaß in Bogenmaß und umgekehrt existieren zwei Funktionen.
class java.lang.Math |
- static double toRadians( double angdeg )
Gradmaß in Bogenmaß umwandeln
- static double toDegrees( double angrad )
Winkel vom Bogenmaß in Gradmaß umwandeln
5.4.4 Runden von Werten 

Für die Rundung von Werten bietet die Klasse Math fünf Funktionen:
class java.lang.Math |
- double ceil( double )
- double floor( double )
- int round( float a ), long round( double a )
- double rint( double )
Auf- und Abrunden mit ceil() und floor()
Die Funktion ceil() dient zum Aufrunden und liefert die nächsthöhere Ganzzahl (jedoch als double, nicht long), wenn die Zahl nicht schon eine ganze Zahl ist; die Funktion floor() rundet auf die nächstniedrige Ganzzahl ab.
Listing 5.3 RoundingDemo.java, Ausschnitt
System.out.println( Math.ceil(-99.1) ); // –99.0 System.out.println( Math.floor(-99.1) ); // –100.0 System.out.println( Math.ceil(-99) ); // –99.0 System.out.println( Math.floor(-99) ); // –99.0 System.out.println( Math.ceil(-.5) ); // –0.0 System.out.println( Math.floor(-.5) ); // –1.0 System.out.println( Math.ceil(-.01) ); // –0.0 System.out.println( Math.floor(-.01) ); // –1.0 System.out.println( Math.ceil(0.1) ); // 1.0 System.out.println( Math.floor(0.1) ); // 0.0 System.out.println( Math.ceil(.5) ); // 1.0 System.out.println( Math.floor(.5) ); // 0.0 System.out.println( Math.ceil(99) ); // 99.0 System.out.println( Math.floor(99) ); // 99.0
Die Funktionen haben auf ganze Zahlen keine Auswirkung.
round()
Die Funktionen round(double) und round(float) runden kaufmännisch auf die nächste Ganzzahl vom Typ long beziehungsweise int. Ganze Zahlen werden nicht aufgerundet. Wir können round() als Gegenstück zur Typumwandlung (long) doublevalue einsetzen.
Listing 5.4 RoundingDemo.java, Ausschnitt
System.out.println( Math.round(1.01) ); // 1 System.out.println( Math.round(1.4) ); // 1 System.out.println( Math.round(1.5) ); // 2 System.out.println( Math.round(1.6) ); // 2 System.out.println( (int) 1.6 ); // 1 System.out.println( Math.round(30) ); // 30 System.out.println( Math.round(-2.1) ); // –2 System.out.println( Math.round(-2.9) ); // –3 System.out.println( (int) –2.9 ); // –2
Beispiel Die round()-Funktion ist in Java ausprogrammiert. Sie addiert auf den aktuellen Parameter 0,5 und übergibt das Ergebnis der floor()-Funktion. public static long round( double a ) { return (int) floor( a + 0.5f ); } |
rint()
rint() ist mit round() vergleichbar, nur ist es im Gegensatz zu round() gerechnet, was bedeutet, dass rint() bei 0,5 in Abhängigkeit davon, ob die benachbarte Zahl ungerade oder gerade ist, auf- oder abrundet.
Listing 5.5 RoundingDemo.java, Ausschnitt
System.out.println( Math.round(-1.5) ); // –1 System.out.println( Math.rint( –1.5) ); // –2.0 System.out.println( Math.round(-2.5) ); // –2 System.out.println( Math.rint( –2.5) ); // –2.0 System.out.println( Math.round( 1.5) ); // 2 System.out.println( Math.rint( 1.5) ); // 2.0 System.out.println( Math.round( 2.5) ); // 3 System.out.println( Math.rint( 2.5) ); // 2.0
Mit dem konsequenten Aufrunden pflanzen sich natürlich auch Fehler ungeschickter fort als mit dieser 50/50-Strategie.
Beispiel Die rint()-Funktion lässt sich auch einsetzen, wenn Zahlen auf zwei Nachkommastellen gerundet werden sollen. Ist d vom Typ double, so ergibt der Ausdruck Math.rint(d*100.0)/100.0 die gerundete Zahl. |
Listing 5.6 Round2Scales.java
class Round2Scales { public static double roundScale2( double d ) { return Math.rint( d * 100 ) / 100.; } public static void main( String[] args ) { System.out.println( roundScale2(+1.341 ) ); // 1.34 System.out.println( roundScale2(–1.341 ) ); // –1.34 System.out.println( roundScale2(+1.345 ) ); // 1.34 System.out.println( roundScale2(–1.345 ) ); // –1.34 System.out.println( roundScale2(+1.347 ) ); // 1.35 System.out.println( roundScale2(–1.347 ) ); // –1.35 } }
Arbeiten wir statt mit rint() mit round(), wird die Zahl 1,345 nicht auf 1,34, sondern auf 1,35 gerundet. Wer nun Lust hat, etwas auszuprobieren, darf testen, wie der Formatstring »%.2f« bei printf() rundet.
5.4.5 Wurzel und Exponentialfunktionen 

Die Math-Klasse bietet weiterhin Funktionen zum Berechnen der Wurzel und weitere Exponentialfunktionen:
class java.lang.Math |
- static double sqrt( double x )
Liefert die Quadratwurzel von x; sqrt steht für square root.
- static double cbrt( double a )
Berechnet die dritte Wurzel aus a.
- static double exp( double x )
Liefert den Exponentialwert von x zur Basis e (der eulerschen Zahl e = 2,71828…), also ex .
- static double expm1( double x )
Liefert den Exponentialwert von x zur Basis e minus 1, also ex – 1. Berechnungen nahe null kann expm1(x) + 1 präziser ausdrücken als exp(x).
- static double pow( double x, double y )
Liefert den Wert der Potenz xy . Für ganzzahlige Werte gibt es keine eigene Funktion.
5.4.6 Der Logarithmus 

Der Logarithmus ist die Umkehrfunktion der Exponentialfunktion. Die Exponentialfunktion und der Logarithmus hängen durch folgende Beziehung zusammen: Ist y = ax , dann ist x = loga(y). Der Logarithmus Math.log() ist der natürliche Logarithmus zur Basis e. In der Mathematik wird dieser mit »ln« angegeben (logarithmus naturalis). Logarithmen mit der Basis 10 heißen dekadische oder Brigg’sche Logarithmen und werden mit »lg« abgekürzt; der Logarithmus zur Basis 2 (binärer Logarithmus, dualer Logarithmus) wird mit »lb« abgekürzt. In Java gibt es die statische Funktion log10() für den Brigg’schen Logarithmus lg, nicht aber für den binären Logarithmus lb, der weiterhin nachgebildet werden muss. Allgemein gilt folgende Umrechnung: logb(x) = loga(x) / loga(b).
Beispiel Eine eigene statische Funktion soll den Logarithmus zur Basis 2 berechnen. public static double lb( double x ) { return Math.log( x ) / Math.log( 2.0 ); } Da Math.log(2) konstant ist, sollte dieser Wert aus Performance-Gründen in einer Konstanten gehalten werden. |
class java.lang.Math |
- static double log( double a )
Berechnet von a den Logarithmus zur Basis e.
- static double log10( double a )
Liefert von a den Logarithmus zur Basis 10.
- static double log1p( double x )
Liefert log(x) + 1.
5.4.7 Rest der ganzzahligen Division 

Neben dem Restwertoperator %, der den Rest der Division berechnet, gibt es auch eine Funktion IEEEremainder() in der Math-Klasse.
Listing 5.7 IEEEremainder.java
public class IEEEremainder { public static void main( String[] args ) { double a = 44.0; double b = 2.2; System.out.println( a / b ); // 20.0 System.out.println( a % b ); // 2.1999999999999966 System.out.println( Math.IEEEremainder( a, b ) ); // –3.552713678800501E-15 } }
Das zweite Ergebnis ist mit der mathematischen Ungenauigkeit fast 2,2, aber etwas kleiner, sodass der Algorithmus nicht noch einmal 2,2 abziehen konnte. Die Funktion IEEEremainder() liefert ein Ergebnis nahe null (–0,0000000000000035527136788005), was besser ist, denn 44,0 lässt sich ohne Rest durch 2,2 teilen, also wäre der Rest eigentlich 0.
class java.lang.Math |
- static double IEEEremainder( double dividend, double divisor )
Liefert den Rest der Division von Dividend und Divisor, so wie es der IEEE-754-Standard vorschreibt.
Eine Funktion, die mitunter bessere Ergebnisse liefert (in unserem Fall wirklich 0,0), ist die folgende:
public static double remainder( double a, double b ) { return Math.signum(a) * (Math.abs(a) – Math.abs(b) * Math.floor(Math.abs(a)/Math.abs(b))); }
5.4.8 Zufallszahlen 

Positive Gleitkomma-Zufallszahlen zwischen größer gleich 0,0 und echt kleiner 1,0 liefert die Funktion Math.random(). Die Rückgabe ist double, und eine Typanpassung auf int führt immer zum Ergebnis 0.
Möchten wir Werte in einem anderen Wertebereich haben, ist es eine einfache Lösung, die Zufallszahlen von Math.random() durch Multiplikation (Skalierung) auf den gewünschten Wertebereich auszudehnen und per Addition (ein Offset) geeignet zu verschieben. Um ganzzahlige Zufallszahlen zwischen min (inklusiv) und max (inklusiv) zu erhalten, schreiben wir:
Listing 5.8 RandomIntInRange.java
public static long random( long min, long max ) { return min + Math.round( Math.random() * (max – min) ); }
Eine Alternative bietet der direkte Einsatz der Klasse Random und der Funktion nextInt(n).