Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Eigene Klassen schreiben
6 Exceptions
7 Äußere.innere Klassen
8 Besondere Klassen der Java SE
9 Generics<T>
10 Architektur, Design und angewandte Objektorientierung
11 Die Klassenbibliothek
12 Einführung in die nebenläufige Programmierung
13 Einführung in Datenstrukturen und Algorithmen
14 Einführung in grafische Oberflächen
15 Einführung in Dateien und Datenströme
16 Einführung in die <XML>-Verarbeitung mit Java
17 Einführung ins Datenbankmanagement mit JDBC
18 Bits und Bytes und Mathematisches
19 Die Werkzeuge des JDK
A Die Klassenbibliothek
Stichwort

Download:
- Aufgaben, ca. 1,1 MB
- Programme, ca. 12,8 MB

Buch bestellen
Ihre Meinung?

Spacer
Java ist auch eine Insel von Christian Ullenboom
Das umfassende Handbuch
Buch: Java ist auch eine Insel

Java ist auch eine Insel
Galileo Computing
1308 S., 10., aktualisierte Auflage, geb., mit DVD
ca. 49,90 Euro, ISBN 978-3-8362-1802-3
Pfeil 18 Bits und Bytes und Mathematisches
Pfeil 18.1 Bits und Bytes *
Pfeil 18.1.1 Die Bit-Operatoren Komplement, Und, Oder und Xor
Pfeil 18.1.2 Repräsentation ganzer Zahlen in Java – das Zweierkomplement
Pfeil 18.1.3 Das binäre (Basis 2), oktale (Basis 8), hexadezimale (Basis 16) Stellenwertsystem
Pfeil 18.1.4 Auswirkung der Typanpassung auf die Bitmuster
Pfeil 18.1.5 byte als vorzeichenlosen Datentyp nutzen
Pfeil 18.1.6 Die Verschiebeoperatoren
Pfeil 18.1.7 Ein Bit setzen, löschen, umdrehen und testen
Pfeil 18.1.8 Bit-Methoden der Integer- und Long-Klasse
Pfeil 18.2 Fließkommaarithmetik in Java
Pfeil 18.2.1 Spezialwerte für Unendlich, Null, NaN
Pfeil 18.2.2 Standard-Notation und wissenschaftliche Notation bei Fließkommazahlen *
Pfeil 18.2.3 Mantisse und Exponent *
Pfeil 18.3 Die Eigenschaften der Klasse Math
Pfeil 18.3.1 Attribute
Pfeil 18.3.2 Absolutwerte und Vorzeichen
Pfeil 18.3.3 Maximum/Minimum
Pfeil 18.3.4 Runden von Werten
Pfeil 18.3.5 Wurzel- und Exponentialmethoden
Pfeil 18.3.6 Der Logarithmus *
Pfeil 18.3.7 Rest der ganzzahligen Division *
Pfeil 18.3.8 Winkelmethoden *
Pfeil 18.3.9 Zufallszahlen
Pfeil 18.4 Genauigkeit, Wertebereich eines Typs und Überlaufkontrolle *
Pfeil 18.4.1 Behandlung des Überlaufs
Pfeil 18.4.2 Was bitte macht ein ulp?
Pfeil 18.5 Mathe bitte strikt *
Pfeil 18.5.1 Strikte Fließkommaberechnungen mit strictfp
Pfeil 18.5.2 Die Klassen Math und StrictMath
Pfeil 18.6 Die Random-Klasse
Pfeil 18.6.1 Objekte mit dem Samen aufbauen
Pfeil 18.6.2 Zufallszahlen erzeugen
Pfeil 18.6.3 Pseudo-Zufallszahlen in der Normalverteilung *
Pfeil 18.7 Große Zahlen *
Pfeil 18.7.1 Die Klasse BigInteger
Pfeil 18.7.2 Methoden von BigInteger
Pfeil 18.7.3 Ganz lange Fakultäten
Pfeil 18.7.4 Große Fließkommazahlen mit BigDecimal
Pfeil 18.7.5 Mit MathContext komfortabel die Rechengenauigkeit setzen
Pfeil 18.8 Zum Weiterlesen

Rheinwerk Computing - Zum Seitenanfang

18.3 Die Eigenschaften der Klasse MathZur nächsten Überschrift

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

Abbildung

Abbildung 18.1: UML-Diagramm der Klasse »Math«


Rheinwerk Computing - Zum Seitenanfang

18.3.1 AttributeZur nächsten ÜberschriftZur vorigen Überschrift

Die Math-Klasse besitzt zwei statische Attribute:

class java.lang.Math

Rheinwerk Computing - Zum Seitenanfang

18.3.2 Absolutwerte und VorzeichenZur nächsten ÜberschriftZur vorigen Überschrift

Die zwei statischen abs()-Methoden 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.

Eine spezielle Methode ist auch copySign(). Sie ermittelt das Vorzeichen einer Fließkommazahl und setzt dieses Vorzeichen bei einer anderen.

class java.lang.Math
  • static int abs(int x)
  • static long abs(long x)
  • static float abs(float x)
  • static double abs(double x)
  • static double copySign(double magnitude, double sign)
  • static float copySign(float magnitude, float sign)
    Liefert magnitude als Rückgabe, aber mit dem Vorzeichen von sign.
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?

Vorzeichen erfragen

Die statische Methode signum(value) liefert eine numerische Rückgabe für das Vorzeichen von value, und zwar +1 für positive, –1 für negative Zahlen, und 0 für 0. Die Methode ist nicht ganz logisch auf die Klassen Math für Fließkommazahlen und Integer/Long für Ganzzahlen verteilt:

  • java.lang.Integer.signum(int i)
  • java.lang.Long.signum(long i)
  • java.lang.Math.signum(double d)
  • java.lang.Math.signum(float f)

Rheinwerk Computing - Zum Seitenanfang

18.3.3 Maximum/MinimumZur nächsten ÜberschriftZur vorigen Überschrift

Die statischen max()-Methoden liefern den größeren der übergebenen Werte. Die statischen min()-Methoden 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)

Rheinwerk Computing - Zum Seitenanfang

18.3.4 Runden von WertenZur nächsten ÜberschriftZur vorigen Überschrift

Für die Rundung von Werten bietet die Klasse Math fünf statische Methoden:

class java.lang.Math
  • static double ceil(double a)
  • static double floor(double a)
  • static int round(float a)
  • static long round(double a)
  • static double rint(double a)

Auf- und Abrunden mit ceil() und floor()

Die statische Methode ceil() dient zum Aufrunden und liefert die nächsthöhere Ganzzahl (jedoch als double, nicht als long), wenn die Zahl nicht schon eine ganze Zahl ist; die statische Methode floor() rundet auf die nächstniedrigere Ganzzahl ab:

Listing 18.1: 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 genannten statischen Methoden haben auf ganze Zahlen keine Auswirkung.

Kaufmännisches Runden mit round()

Die statischen Methoden 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 18.2: 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 Math.round()-Methode ist in Java ausprogrammiert. Sie addiert auf den aktuellen Parameter 0,5 und übergibt das Ergebnis der statischen floor()-Methode:

public static long round( double a ) {
return (int) floor( a + 0.5f );
}

Gerechtes Runden rint()

rint() ist mit round() vergleichbar, nur ist es im Gegensatz zu round() gerecht, was bedeutet, dass rint() bei 0,5 in Abhängigkeit davon, ob die benachbarte Zahl ungerade oder gerade ist, auf- oder abrundet:

Listing 18.3: 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 einem konsequenten Auf- oder Abrunden pflanzen sich natürlich auch Fehler ungeschickter fort als mit dieser 50/50-Strategie.

Beispiel

Die statische rint()-Methode 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 18.4: 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.


Rheinwerk Computing - Zum Seitenanfang

18.3.5 Wurzel- und ExponentialmethodenZur nächsten ÜberschriftZur vorigen Überschrift

Die Math-Klasse bietet weiterhin Methoden zum Berechnen der Wurzel und weitere Exponentialmethoden.

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 hypot(double x, double y)
    Berechnet die Wurzel aus x2 + y2, also den euklidischen Abstand. Könnte als sqrt(x*x, y*y) umgeschrieben werden, doch hypot() bietet eine bessere Genauigkeit und Performance.
  • static double scalb(double d, double scaleFactor)
    Liefert d mal 2 hoch scaleFactor. Kann prinzipiell auch als d * Math.pow(2, scaleFactor) geschrieben werden, doch scalb() bietet eine bessere Performance.
  • 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 Methode.

Die Frage nach dem 0.0/0.0 und 0.0^0.0 *

Wie wir wissen, ist 0.0/0.0 ein glattes NaN. Im Unterschied zu den Ganzzahlwerten bekommen wir hier allerdings keine Exception, denn dafür ist extra die Spezialzahl NaN eingeführt worden. Interessant ist die Frage, was denn (long)(double)(0.0/0.0) ergibt. Die Sprachdefinition sagt hier in §5.1.3, dass die Konvertierung eines Fließkommawerts NaN in ein int 0 oder long 0 ergibt.[222](Leider gab es in den ersten Versionen der JVM einen Fehler, sodass Long.MAX_VALUE anstelle von 0.0 produziert wurde. Dieser Fehler ist aber inzwischen behoben.)

Eine weitere spannende Frage ist das Ergebnis von 0.0^0.0. Um allgemeine Potenzen zu berechnen, wird die statische Funktion Math.pow(double a, double b) eingesetzt. Wir erinnern uns aus der Schulzeit daran, dass wir die Quadratwurzel einer Zahl ziehen, wenn der Exponent b genau 1/2 ist. Doch jetzt wollen wir wissen, was denn gilt, wenn a = b = 0 gilt. §20.11.13 der Sprachdefinition fordert, dass das Ergebnis immer 1.0 ist, wenn der Exponent b gleich –0.0 oder 0.0 ist. Es kommt also in diesem Fall überhaupt nicht auf die Basis a an. In einigen Algebra-Büchern wird 0^0 als undefiniert behandelt. Es macht aber durchaus Sinn, 0^0 als 1 zu definieren, da es andernfalls viele Sonderbehandlungen für 0 geben müsste.[223](Hier schreiben die Autoren R. Graham, D. Knuth, O. Patashnik des Buchs Concrete Mathematics: »Some textbooks leave the quantity 0^0 undefined, because the functions x^0 and 0^x have different limiting values when x decreases to 0. But this is a mistake. We must define x^0 = 1 for all x, if the binomial theorem is to be valid when x=0, y=0, and/or x=-y. The theorem is too important to be arbitrarily restricted! By contrast, the function 0^x is quite unimportant.«, Addison-Wesley, 1994, ISBN 0-201-55802-5.)


Rheinwerk Computing - Zum Seitenanfang

18.3.6 Der Logarithmus *Zur nächsten ÜberschriftZur vorigen Überschrift

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, den Math.log() berechnet, 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 briggsche 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 Methode log10() für den briggschen 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 Methode 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.

Rheinwerk Computing - Zum Seitenanfang

18.3.7 Rest der ganzzahligen Division *Zur nächsten ÜberschriftZur vorigen Überschrift

Neben dem Restwert-Operator %, der den Rest der Division berechnet, gibt es auch eine statische Methode Math.IEEEremainder().

Listing 18.5: IEEEremainder.java, main()

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 statische Methode IEEEremainder() liefert ein Ergebnis nahe null (–0,000000000000003552713 6788005), 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 eigene statische Methode, die mitunter bessere Ergebnisse liefert – mit den Werten 44 und 2,2 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)));
}

Rheinwerk Computing - Zum Seitenanfang

18.3.8 Winkelmethoden *Zur nächsten ÜberschriftZur vorigen Überschrift

Die Math-Klasse stellt einige winkelbezogene Methoden und ihre Umkehrungen zur Verfügung. Im Gegensatz zur bekannten Schulmathematik werden die Winkel für sin(), cos(), tan() im Bogenmaß (2p entspricht einem Vollkreis) und nicht im Gradmaß (360 Grad entspricht einem Vollkreis) übergeben.

class java.lang.Math
  • static double sin(double x)
  • static double cos(double x)
  • static double tan(double x)
    Liefert den Sinus/Kosinus/Tangens von x.

Arcus-Methoden

Die Arcus-Methoden realisieren die Umkehrfunktionen zu den trigonometrischen Methoden. 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 –p/2 und p/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 beziehungsweise 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 statische Methode berücksichtigt das Vorzeichen der Parameter x und y, und der freie Schenkel des Winkels befindet sich im richtigen Quadranten.

Hyperbolicus-Methoden bietet Java über sinh(), tanh() und cosh().

Umrechnungen von Gradmaß in Bogenmaß

Zur Umwandlung eines Winkels von Gradmaß in Bogenmaß und umgekehrt existieren zwei statische Methoden:

class java.lang.Math
  • static double toRadians(double angdeg)
    Wandelt Winkel von Gradmaß in Bogenmaß um.
  • static double toDegrees(double angrad)
    Wandelt Winkel von Bogenmaß in Gradmaß um.

Rheinwerk Computing - Zum Seitenanfang

18.3.9 ZufallszahlenZur vorigen Überschrift

Positive Gleitkomma-Zufallszahlen zwischen größer gleich 0,0 und echt kleiner 1,0 liefert die statische Methode 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 18.6: 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 Objektmethode nextInt(n).



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Java ist auch eine Insel





Java ist auch eine Insel
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Java ist auch eine Insel






 Java ist auch
 eine Insel


Zum Katalog: Java SE Bibliotheken






 Java SE Bibliotheken


Zum Katalog: Professionell entwickeln mit Java EE 7






 Professionell
 entwickeln mit
 Java EE 7


Zum Katalog: Einstieg in Eclipse






 Einstieg in
 Eclipse


Zum Katalog: Einstieg in Java






 Einstieg in
 Java


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2011
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de