Galileo Computing < openbook >Galileo 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:
- openbook, ca. 24,5 MB
- 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
Pfeil18 Bits und Bytes und Mathematisches
Pfeil18.1 Bits und Bytes *
Pfeil18.1.1 Die Bit-Operatoren Komplement, Und, Oder und Xor
Pfeil18.1.2 Repräsentation ganzer Zahlen in Java – das Zweierkomplement
Pfeil18.1.3 Das binäre (Basis 2), oktale (Basis 8), hexadezimale (Basis 16) Stellenwertsystem
Pfeil18.1.4 Auswirkung der Typanpassung auf die Bitmuster
Pfeil18.1.5 byte als vorzeichenlosen Datentyp nutzen
Pfeil18.1.6 Die Verschiebeoperatoren
Pfeil18.1.7 Ein Bit setzen, löschen, umdrehen und testen
Pfeil18.1.8 Bit-Methoden der Integer- und Long-Klasse
Pfeil18.2 Fließkommaarithmetik in Java
Pfeil18.2.1 Spezialwerte für Unendlich, Null, NaN
Pfeil18.2.2 Standard-Notation und wissenschaftliche Notation bei Fließkommazahlen *
Pfeil18.2.3 Mantisse und Exponent *
Pfeil18.3 Die Eigenschaften der Klasse Math
Pfeil18.3.1 Attribute
Pfeil18.3.2 Absolutwerte und Vorzeichen
Pfeil18.3.3 Maximum/Minimum
Pfeil18.3.4 Runden von Werten
Pfeil18.3.5 Wurzel- und Exponentialmethoden
Pfeil18.3.6 Der Logarithmus *
Pfeil18.3.7 Rest der ganzzahligen Division *
Pfeil18.3.8 Winkelmethoden *
Pfeil18.3.9 Zufallszahlen
Pfeil18.4 Genauigkeit, Wertebereich eines Typs und Überlaufkontrolle *
Pfeil18.4.1 Behandlung des Überlaufs
Pfeil18.4.2 Was bitte macht ein ulp?
Pfeil18.5 Mathe bitte strikt *
Pfeil18.5.1 Strikte Fließkommaberechnungen mit strictfp
Pfeil18.5.2 Die Klassen Math und StrictMath
Pfeil18.6 Die Random-Klasse
Pfeil18.6.1 Objekte mit dem Samen aufbauen
Pfeil18.6.2 Zufallszahlen erzeugen
Pfeil18.6.3 Pseudo-Zufallszahlen in der Normalverteilung *
Pfeil18.7 Große Zahlen *
Pfeil18.7.1 Die Klasse BigInteger
Pfeil18.7.2 Methoden von BigInteger
Pfeil18.7.3 Ganz lange Fakultäten
Pfeil18.7.4 Große Fließkommazahlen mit BigDecimal
Pfeil18.7.5 Mit MathContext komfortabel die Rechengenauigkeit setzen
Pfeil18.8 Zum Weiterlesen

Galileo Computing - Zum Seitenanfang

18.4 Genauigkeit, Wertebereich eines Typs und Überlaufkontrolle *Zur nächsten Überschrift

Für jeden primitiven Datentyp gibt es in Java eine eigene Klasse mit diversen Methoden und Konstanten. Die Klassen Byte, Short, Integer, Long, Float und Double besitzen die Konstanten MIN_VALUE und MAX_VALUE für den minimalen und maximalen Wertebereich. Die Klassen Float und Double verfügen zusätzlich über die wichtigen Konstanten NEGATIVE_INFINITY und POSITIVE_INFINITY für minus und plus unendlich und NaN (Not a Number, undefiniert).

Hinweis

Integer.MIN_VALUE steht mit –2147483648 für den kleinsten Wert, den die Ganzzahl annehmen kann. Double.MIN_VALUE steht jedoch für die kleinste positive Zahl (beste Näherung an 0), die ein Double darstellen kann (4.9E–324).

Wenn uns beim Wort double im Vergleich zu float eine »doppelte Genauigkeit« über die Lippen kommt, müssen wir mit der Aussage vorsichtig sein, denn double bietet zumindest nach der Anzahl der Bits eine mehr als doppelt so präzise Mantisse. Über die Anzahl der Nachkommastellen sagt das jedoch direkt nichts aus.

Bastelaufgabe

Warum sind die Ausgaben so, wie sie sind?

Listing 18.7: DoubleFloatEqual.java, main()

double d1 = 0.02d;
float f1 = 0.02f;
System.out.println( d1 == f1 ); // false
System.out.println( (float) d1 == f1 ); // true

double d2 = 0.02f;
float f2 = 0.02f;
System.out.println( d2 == f2 ); // true


Galileo Computing - Zum Seitenanfang

18.4.1 Behandlung des ÜberlaufsZur nächsten ÜberschriftZur vorigen Überschrift

Bei einigen mathematischen Fragestellungen müssen Sie feststellen können, ob Operationen wie die Addition, Subtraktion oder Multiplikation den Zahlenbereich sprengen, also etwa den Ganzzahlenbereich eines Integers von 32 Bit verlassen. Passt das Ergebnis einer Berechnung nicht in den Wertebereich einer Zahl, so wird dieser Fehler nicht von Java angezeigt; weder der Compiler noch die Laufzeitumgebung melden dieses Problem. Es gibt auch keine Ausnahme.

Mathematisch gilt a × a / a = a, also zum Beispiel 100 000 × 100 000 / 100 000 = 100 000. In Java ist das anders, da wir bei 100 000 × 100 000 einen Überlauf im int haben.

System.out.println( 100000 * 100000 / 100000 );     // 14100

liefert daher 14100. Wenn wir den Datentyp auf long erhöhen, indem wir hinter ein 100 000 ein L setzen, sind wir bei dieser Multiplikation noch sicher, da ein long das Ergebnis aufnehmen kann.

System.out.println( 100000L * 100000 / 100000 );    // 100000

Überlauf erkennen

Für die Operationen Addition und Subtraktion lässt sich das noch ohne allzu großen Aufwand implementieren. Wir vergleichen dazu zunächst das Ergebnis mit den Konstanten Integer.MAX_VALUE und Integer.MIN_VALUE. Natürlich muss der Vergleich so umgeformt werden, dass dabei kein Überlauf auftritt, also a + b > Integer.MAX_VALUE ist. Überschreiten die Werte diese maximalen Werte, ist die Operation nicht ohne Fehler möglich, und wir setzen das Flag canAdd auf false. Hier die Programmzeilen für die Addition:

if ( a >=0 && b >= 0 )
if ( ! (b <= Integer.MAX_VALUE – a) )
canAdd = false;
if ( a < 0 && b < 0 )
if ( ! (b >= Integer.MIN_VALUE – a) )
canAdd = false;

Bei der Multiplikation gibt es zwei Möglichkeiten: Zunächst einmal lässt sich die Multiplikation als Folge von Additionen darstellen. Dann ließe sich wiederum der Test mit der Konstanten Integer.XXX_VALUE durchführen. Diese Lösung scheidet jedoch wegen der Geschwindigkeit aus. Der andere Weg sieht eine Umwandlung nach long vor. Das Ergebnis wird zunächst als long berechnet und anschließend mit dem Ganzzahlwert vom Typ int verglichen.

Dies funktioniert jedoch nur mit Datentypen, die kleiner als long sind. long selbst fällt heraus, da es keinen Datentyp gibt, der größer ist. Mit ein wenig Rechenungenauigkeit würde ein double jedoch weiterhelfen, und bei präziserer Berechnung kann BigInteger helfen. Bei der Multiplikation im Wertebereich int lässt sich ähnlich wie bei der Addition auch b > Integer.MAX_VALUE / a schreiben. Bei b == Integer.MAX_VALUE / a muss ein Test genau zeigen, ob das Ergebnis in den Wertebereich passt.

Die eigene statische Methode canMulLong() soll bei der Frage nach dem Überlauf helfen:

Listing 18.8: Overflow.java

import java.math.BigInteger;

public class Overflow
{
private final static BigInteger MAX = BigInteger.valueOf( Long.MAX_VALUE );

public static boolean canMulLong( long a, long b )
{
BigInteger bigA = BigInteger.valueOf( a );
BigInteger bigB = BigInteger.valueOf( b );

return bigB.multiply( bigA ).compareTo( MAX ) <= 0;
}

public static void main( String[] args )
{
System.out.println( canMulLong(Long.MAX_VALUE/2, 2) ); // true
System.out.println( Long.MAX_VALUE/2 * 2 ); // 9223372036854775806
System.out.println( canMulLong(Long.MAX_VALUE/2 + 1, 2) ); // false
System.out.println( (Long.MAX_VALUE/2 + 1) * 2 ); //-9223372036854775808
}
}
Hinweis

Wenn der Compiler beziehungsweise die JVM genau das macht, was wir uns wünschen, so würde auch ein return a * b / b == a; reichen. Doch eine JVM kann das zu return a == a; optimieren und somit zu return true; machen, sodass der Test nicht funktioniert.


Galileo Computing - Zum Seitenanfang

18.4.2 Was bitte macht ein ulp?Zur vorigen Überschrift

Die Math-Klasse bietet sehr spezielle Methoden, die für diejenigen interessant sind, die sich sehr genau mit Rechen(un)genauigkeiten beschäftigen und mit numerischen Näherungen arbeiten.

Der Abstand von einer Fließkommazahl zur nächsten ist durch den internen Aufbau nicht immer gleich. Wie groß genau der Abstand einer Zahl zur nächstmöglichen ist, zeigt ulp(double) beziehungsweise ulp(float). Der lustige Methodenname ist eine Abkürzung für Unit in the Last Place. Was genau denn die nächsthöhere/-niedrigere Zahl ist, ermitteln die Methoden nextUp(double)/nextUp(float), die auf nextAfter() zurückgreifen.

Beispiel

Was kommt nach und vor 1:

System.out.printf( "%.16f%n", Math.nextUp( 1 ) );
System.out.printf( "%.16f%n", Math.nextAfter( 1, Double.POSITIVE_INFINITY ) );
System.out.printf( "%.16f%n", Math.nextAfter( 1, Double.NEGATIVE_INFINITY ) );
Die Ausgabe ist:
1,0000001192092896
1,0000001192092896
0,9999999403953552
nextUp() ist eine Abkürzung wie für den Ausdruck in der zweiten Zeile. Ist das zweite Argument von Math.nextAfter() größer als das erste, dann wird die nächstgrößere Zahl zurückgegeben, ist sie kleiner, dann die nächstkleinere Zahl. Bei Gleichheit kommt die gleiche Zahl zurück.

Dazu ein weiteres Beispiel: Je größer die Zahlen werden, desto größer werden auch die Sprünge.

Tabelle 18.11: Da das Vorzeichen in einem extra Bit gespeichert ist, haben negative
oder positive Zahlen keine anderen Genauigkeiten.

Methode Rückgabe des ulp
Math.ulp( 0.00001 ) 0,000000000000000000001694065895
Math.ulp( –1 ) 0,00000011920928955078125
Math.ulp( 1 ) 0,00000011920928955078125
Math.ulp( 2 ) 0,0000002384185791015625
Math.ulp( 10E30 ) 1125899906842624

Die üblichen mathematischen Fließkommaoperationen haben eine ulp von ½. Das ist so genau wie möglich. Um wie viel ulp die Math-Methoden vom echten Resultat abweichen können, steht in der JavaDoc. Rechenfehler lassen sich insbesondere bei komplexen Methoden nicht vermeiden. So darf sin() eine mögliche Ungenauigkeit von 1 ulp haben, atan2() von maximal 2 ulp und sinh(), chosh(), tanh() von 2,5 ulp.

Die ulp()-Methode ist für das Testen interessant, denn mit ihr lassen sich Abweichungen immer in der passenden Größenordnung realisieren. Bei kleinen Zahlen ergibt eine Differenz von vielleicht 0,001 einen Sinn, bei größeren Zahlen kann die Toleranz größer sein.

Java deklariert in den Klassen Double und Float drei besondere Konstanten. Sie lassen sich gut mit nextAfter() erklären. Am Beispiel von Double:

  • MIN_VALUE = nextUp(0.0) = Double.longBitsToDouble(0x0010000000000000L)
  • MIN_NORMAL = MIN_VALUE/(nextUp(1.0)-1.0) = Double.longBitsToDouble(0x1L)
  • MAX_VALUE = nextAfter(POSITIVE_INFINITY, 0.0) =
    Double.longBitsToDouble(0x7fefffffffffffffL)


Ihr Kommentar

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







<< 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 7 – Mehr als eine Insel





 Java 7 –
 Mehr als eine Insel


Zum Katalog: Android 3






 Android 3


Zum Katalog: Android-Apps entwickeln






 Android-Apps
 entwickeln


Zum Katalog: NetBeans Platform 7






 NetBeans
 Platform 7


Zum Katalog: Einstieg in Eclipse 3.7






 Einstieg in
 Eclipse 3.7


Zum Katalog: Einstieg in Java






 Einstieg
 in Java


Zum Katalog: Einstieg in Java 7






 Einstieg in
 Java 7


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 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.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de