Rheinwerk Computing < openbook >


 
Inhaltsverzeichnis
Materialien
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Arrays und ihre Anwendungen
5 Der Umgang mit Zeichenketten
6 Eigene Klassen schreiben
7 Objektorientierte Beziehungsfragen
8 Ausnahmen müssen sein
9 Geschachtelte Typen
10 Besondere Typen der Java SE
11 Generics<T>
12 Lambda-Ausdrücke und funktionale Programmierung
13 Architektur, Design und angewandte Objektorientierung
14 Java Platform Module System
15 Die Klassenbibliothek
16 Einführung in die nebenläufige Programmierung
17 Einführung in Datenstrukturen und Algorithmen
18 Einführung in grafische Oberflächen
19 Einführung in Dateien und Datenströme
20 Einführung ins Datenbankmanagement mit JDBC
21 Bits und Bytes, Mathematisches und Geld
22 Testen mit JUnit
23 Die Werkzeuge des JDK
A Java SE-Module und Paketübersicht
Stichwortverzeichnis


Download:

- Listings, ca. 2,7 MB


Buch bestellen
Ihre Meinung?



Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom

Einführung, Ausbildung, Praxis
Buch: Java ist auch eine Insel


Java ist auch eine Insel

Pfeil 21 Bits und Bytes, Mathematisches und Geld
Pfeil 21.1 Bits und Bytes
Pfeil 21.1.1 Die Bit-Operatoren Komplement, Und, Oder und XOR
Pfeil 21.1.2 Repräsentation ganzer Zahlen in Java – das Zweierkomplement
Pfeil 21.1.3 Das binäre (Basis 2), oktale (Basis 8), hexadezimale (Basis 16) Stellenwertsystem
Pfeil 21.1.4 Auswirkung der Typumwandlung auf die Bit-Muster
Pfeil 21.1.5 Vorzeichenlos arbeiten
Pfeil 21.1.6 Die Verschiebeoperatoren
Pfeil 21.1.7 Ein Bit setzen, löschen, umdrehen und testen
Pfeil 21.1.8 Bit-Methoden der Integer- und Long-Klasse
Pfeil 21.2 Fließkomma-Arithmetik in Java
Pfeil 21.2.1 Spezialwerte für Unendlich, Null, NaN
Pfeil 21.2.2 Standardnotation und wissenschaftliche Notation bei Fließkommazahlen *
Pfeil 21.2.3 Mantisse und Exponent *
Pfeil 21.3 Die Eigenschaften der Klasse Math
Pfeil 21.3.1 Attribute
Pfeil 21.3.2 Absolutwerte und Vorzeichen
Pfeil 21.3.3 Maximum/Minimum
Pfeil 21.3.4 Runden von Werten
Pfeil 21.3.5 Rest der ganzzahligen Division *
Pfeil 21.3.6 Division mit Rundung in Richtung negativ unendlich, alternativer Restwert *
Pfeil 21.3.7 Multiply-Accumulate
Pfeil 21.3.8 Wurzel- und Exponentialmethoden
Pfeil 21.3.9 Der Logarithmus *
Pfeil 21.3.10 Winkelmethoden *
Pfeil 21.3.11 Zufallszahlen
Pfeil 21.4 Genauigkeit, Wertebereich eines Typs und Überlaufkontrolle *
Pfeil 21.4.1 Der größte und der kleinste Wert
Pfeil 21.4.2 Überlauf und alles ganz exakt
Pfeil 21.4.3 Was bitte macht eine ulp?
Pfeil 21.5 Zufallszahlen: Random, SecureRandom und SplittableRandom
Pfeil 21.5.1 Die Klasse Random
Pfeil 21.5.2 Random-Objekte mit dem Samen aufbauen
Pfeil 21.5.3 Einzelne Zufallszahlen erzeugen
Pfeil 21.5.4 Pseudo-Zufallszahlen in der Normalverteilung *
Pfeil 21.5.5 Strom von Zufallszahlen generieren *
Pfeil 21.5.6 Die Klasse SecureRandom *
Pfeil 21.5.7 SplittableRandom *
Pfeil 21.6 Große Zahlen *
Pfeil 21.6.1 Die Klasse BigInteger
Pfeil 21.6.2 Beispiel: Ganz lange Fakultäten mit BigInteger
Pfeil 21.6.3 Große Fließkommazahlen mit BigDecimal
Pfeil 21.6.4 Mit MathContext komfortabel die Rechengenauigkeit setzen
Pfeil 21.6.5 Noch schneller rechnen durch mutable Implementierungen
Pfeil 21.7 Mathe bitte strikt *
Pfeil 21.7.1 Strikte Fließkommaberechnungen mit strictfp
Pfeil 21.7.2 Die Klassen Math und StrictMath
Pfeil 21.8 Geld und Währung
Pfeil 21.8.1 Geldbeträge repräsentieren
Pfeil 21.8.2 ISO 4217
Pfeil 21.8.3 Währungen in Java repräsentieren
Pfeil 21.9 Zum Weiterlesen
 

Zum Seitenanfang

21.5    Zufallszahlen: Random, SecureRandom und SplittableRandom Zur vorigen ÜberschriftZur nächsten Überschrift

Die Math-Klasse bietet mit random() eine einfache Methode für Zufallszahlen. Intern basiert sie jedoch auf einer anderen Klasse, die wir auch direkt nutzen können, womit wir die Möglichkeit haben, nicht nur Zufallszahlen zwischen 0 und 1 zu erfragen.

Die üblichen Zufallszahlen von Java sind sogenannte Pseudozufallszahlen, weil sie von einem mathematischen Algorithmus erzeugt werden. Gute »Zufallswerte« wiederholen sich erst nach sehr langen Sequenzen, haben keinen offensichtlichen Zusammenhang und sind schnell generiert. Perfekte Zufallszahlen wären nie vorhersehbar, die Wahrscheinlichkeit für jede Zahl wäre immer gleich – unabhängig von den vorangehenden Werten –, und die Sequenzen würden sich nie wiederholen.

 

Zum Seitenanfang

21.5.1    Die Klasse Random Zur vorigen ÜberschriftZur nächsten Überschrift

Die Klasse Random im java.util-Paket implementiert einen Generator für Pseudozufallszahlen. Im Gegensatz zu Math.random() bietet Random keine statischen Funktionen, sondern eine Reihe von nextXXX(…)-Methoden. Die statische Funktion Math.random() nutzt intern ein Random-Objekt.

 

Zum Seitenanfang

21.5.2    Random-Objekte mit dem Samen aufbauen Zur vorigen ÜberschriftZur nächsten Überschrift

Jedes Random-Objekt benötigt für die Berechnung einen Startwert. Der Startwert für jede Zufallszahl ist ein 48-Bit-Seed. »Seed« ist das englische Wort für »Samen« und deutet an, dass es bei der Generierung von Zufallszahlen wie bei Pflanzen einen Samen gibt, der zu Nachkommen führt. Aus diesem Startwert ermittelt der Zufallszahlengenerator anschließend die folgenden Zahlen durch lineare Kongruenzen. (Dadurch sind die Zahlen nicht wirklich zufällig, sondern gehorchen einem mathematischen Verfahren.)

Am Anfang steht ein Exemplar der Klasse Random. Dieses Exemplar wird mit einem Zufallswert (Datentyp long) initialisiert, der dann für die weiteren Berechnungen verwendet wird. Dieser Startwert prägt die ganze Folge von erzeugten Zufallszahlen, obwohl nicht ersichtlich ist, wie sich die Folge verhält. Doch eines ist gewiss: Zwei mit gleichen Startwerten erzeugte Random-Objekte liefern auch dieselbe Folge von Zufallszahlen, sprich: Ist der Samen der gleiche, ist natürlich auch die Folge der Zufallszahlen immer gleich. Für Tests ist das gar nicht so schlecht. Der parameterlose Konstruktor von Random initialisiert den Startwert mit der Summe aus einem magischen Startwert und System.nanoTime().

class java.util.Random

implements Serializable
  • Random()

    Erzeugt einen neuen Zufallszahlengenerator.

  • Random(long seed)

    Erzeugt einen neuen Zufallszahlengenerator und benutzt den Parameter seed als Startwert.

  • void setSeed(long seed)

    Setzt den Seed neu. Der Generator verhält sich anschließend genauso wie ein mit diesem Seed-Wert frisch erzeugter Generator.

 

Zum Seitenanfang

21.5.3    Einzelne Zufallszahlen erzeugen Zur vorigen ÜberschriftZur nächsten Überschrift

Die Random-Klasse erzeugt Zufallszahlen für vier verschiedene Datentypen: int (32 Bit), long (64 Bit), double und float. Dafür stehen vier Methoden zur Verfügung:

  • int nextInt()

  • long nextLong()

    Liefern die nächste Pseudo-Zufallszahl aus dem gesamten Wertebereich, also zwischen Integer.MIN_VALUE und Integer.MAX_VALUE bzw. Long.MIN_VALUE und Long.MAX_VALUE.

  • float nextFloat()

  • double nextDouble()

    Liefern die nächste Pseudo-Zufallszahl zwischen 0,0 und 1,0.

  • int nextInt(int range)

    Liefert eine int-Pseudo-Zufallszahl im Bereich von 0 bis range.

Die Klasse Random verfügt über eine besondere Methode, mit der sich gleich eine Reihe von Zufallszahlen erzeugen lässt. Dies ist die Methode nextBytes(byte[]). Der Parameter ist ein Byte-Array, und dieses wird komplett mit Zufallszahlen gefüllt.

Hinter allen Methoden zur Erzeugung von Zufallszahlen steckt die Methode next(int bits). Sie ist in Random implementiert, aber durch die Sichtbarkeit protected nur von einer erbenden Klasse sichtbar. Unterklassen sind möglich, denn Random ist eine ganz normale öffentliche nichtfinale Klasse.

 

Zum Seitenanfang

21.5.4    Pseudo-Zufallszahlen in der Normalverteilung * Zur vorigen ÜberschriftZur nächsten Überschrift

Über eine spezielle Methode können wir Zufallszahlen erhalten, die einer Normalverteilung genügen: nextGaussian(). Diese Methode arbeitet intern nach der sogenannten Polar-Methode und erzeugt aus zwei unabhängigen Pseudo-Zufallszahlen zwei normalverteilte Zahlen. Der Mittelpunkt liegt bei 0, und die Standardabweichung ist 1. Die Werte, die nextGaussian() gibt, sind double-Zahlen und häufig in der Nähe von 0. Größere Zahlen sind der Wahrscheinlichkeit nach seltener.

class java.util.Random

implements Serializable
  • double nextGaussian()

    Liefert die nächste Zufallszahl in einer gaußschen Normalverteilung mit der Mitte 0,0 und der Standardabweichung 1,0.

 

Zum Seitenanfang

21.5.5    Strom von Zufallszahlen generieren * Zur vorigen ÜberschriftZur nächsten Überschrift

Sind mehrere Zufallszahlen nötig, ist eine Schleife mit wiederholten Aufrufen von nextXXX() nicht nötig. Stattdessen gibt es in Random zwei Sorten von Methoden, die ein Bündel von Zufallszahlen liefern.

Als Erstes:

  • void nextBytes(byte[] bytes)

    Füllt das Array bytes mit Zufallsbytes auf.

Weitere Methoden liefern einen Stream von Zufallszahlen:

  • IntStream ints(…)

  • LongStream longs(…)

  • DoubleStream doubles(…)

[zB]  Beispiel

Liefere zehn zufällige Zahlen, die vermutlich Primzahlen sind:

LongStream stream = new Random().longs()

.filter( v -> BigInteger.valueOf( v ).isProbablePrime(5) );

stream.limit( 10 ).forEach( System.out::println );

Die Methoden ints(…), longs(…) und doubles(…) gibt es in vier Spielarten, siehe Tabelle 21.13.

Parametrisierung

Erklärung

IntStream ints()

Liefern einen unendlichen Strom von Zufallszahlen im kompletten Wertebereich der Primitiven.

LongStream longs()

DoubleStream doubles()

ints(long streamSize)

Liefern einen Strom mit streamSize Zufallszahlen.

longs(long streamSize)

doubles(long streamSize)

ints(int randomNumberOrigin,

int randomNumberBound)

Liefern einen unendlichen Strom von Zufallszahlen mit Werten im Bereich von randomNumberOrigin (inklusiv) bis randomNumberBound (exklusiv).

longs(long randomNumberOrigin,

long randomNumberBound)

doubles(double randomNumberOrigin,

double randomNumberBound)

ints(long streamSize, int

randomNumberOrigin, int

randomNumberBound)

Liefern einen Strom mit streamSize Zufallszahlen mit Werten im Bereich von randomNumberOrigin (inklusiv) bis randomNumberBound (exklusiv).

longs(long streamSize, long

randomNumberOrigin, long

randomNumberBound)

doubles(long streamSize, double

randomNumberOrigin, double

randomNumberBound)

Tabelle 21.13    Stream-Methoden der Random-Klasse

[zB]  Beispiel

Gib fünf Fließkomma-Zufallszahlen im Bereich von 10 bis 20 aus:

new Random().doubles(5, 10, 20).forEach( System.out::println );
 

Zum Seitenanfang

21.5.6    Die Klasse SecureRandom * Zur vorigen ÜberschriftZur nächsten Überschrift

Die Random-Klasse steckt in der Zwickmühle, auf der einen Seite gute und zufällige Zahlen zu erzeugen, auf der anderen Seite aber auch schnell zu sein. Kryptografisch ordentliche Zahlen erzeugt Random nicht, dafür müsste die Implementierung mehr Aufwand treiben (was mehr Zeit kostet), und so gute Zufallszahlen sind im Alltag auch gar nicht nötig.

Kryptografisch bessere Zufallszahlen liefert java.security.SecureRandom, eine Unterklasse von Random. Als Unterklasse bietet sie natürlich den gleichen Satz an nextXXX(…)-Methoden, nur ist eben die Qualität der Zufallszahlen besser. Das liegt nicht an SecureRandom selbst, denn die Klasse realisiert keine Algorithmen, sondern an den referenzierten austauschbaren Zufallszahlen-Providern. Eine Implementierung liefert SecureRandom.getInstanceStrong() oder auch der parameterlose Konstruktor. Dann muss das SecureRandom-Objekt aber nicht zwingend »stark« sein, also höchsten kryptografischen Standards entsprechen. Den Unterschied gibt es, denn new SecureRandom().getAlgorithm().toString() liefert SHA1PRNG, und SecureRandom.getInstanceStrong().getAlgorithm().toString() gibt Windows-PRNG zurück.

 

Zum Seitenanfang

21.5.7    SplittableRandom * Zur vorigen ÜberschriftZur nächsten Überschrift

Die Klasse SplittableRandom aus dem java.util-Paket hat die Aufgabe, Folgen guter Zufallszahlen zu liefern. (Auch wenn die Klasse SplittableRandom heißt, hat sie mit einem java. util.Spliterator nichts zu tun.) Während bei Random eher die einzelne Zufallszahl im Mittelpunkt steht, rückt SplittableRandom Folgen von Zufallszahlen in den Mittelpunkt, die insbesondere den Dieharder-Test[ 276 ](http://www.phy.duke.edu/~rgb/General/dieharder.php) bestehen.

Die Methoden von SplittableRandom drehen sich daher auch um Ströme von Zufallszahlen, die als IntStream, LongStream und DoubleStream geliefert werden. Zudem gibt es auch die auf Random bekannten nextXXX()-Methoden und eine Methode split(), die ein neues SplittableRandom liefert, sodass zwei parallele Threads weiterhin unabhängig gute Zufallszahlen bekommen.

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java ist auch eine Insel Java ist auch eine Insel

Jetzt Buch bestellen


 Buchempfehlungen
Zum Rheinwerk-Shop: Captain CiaoCiao erobert Java

Captain CiaoCiao erobert Java




Zum Rheinwerk-Shop: Java SE 9 Standard-Bibliothek

Java SE 9 Standard-Bibliothek




Zum Rheinwerk-Shop: Algorithmen in Java

Algorithmen in Java




Zum Rheinwerk-Shop: Objektorientierte Programmierung

Objektorientierte Programmierung




 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz

InfoInfo



 

 


Copyright © Rheinwerk Verlag GmbH 2021

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



Cookie-Einstellungen ändern