4099 Stimmen

Wie erzeuge ich in Java zufällige Ganzzahlen innerhalb eines bestimmten Bereichs?

Wie generiere ich eine zufällige int Wert in einem bestimmten Bereich?

Ich habe Folgendes versucht, aber das funktioniert nicht:

Versuch 1:

randomNum = minimum + (int)(Math.random() * maximum);

Fehler: randomNum kann größer sein als maximum .

Versuch 2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;

Fehler: randomNum kann kleiner sein als minimum .

0 Stimmen

Wenn Sie viele Zufallszahlen benötigen, empfehle ich die Klasse Random in der API nicht. Sie hat einfach eine zu kleine Periode. Versuchen Sie die Mersenne-Twister stattdessen. Es gibt eine Java-Implementierung .

46 Stimmen

Bevor Sie eine neue Antwort schreiben, bedenken Sie, dass es bereits mehr als 65 Antworten auf diese Frage gibt. Bitte stellen Sie sicher, dass Ihre Antwort Informationen enthält, die nicht in den vorhandenen Antworten enthalten sind.

4374voto

Greg Case Punkte 45093

Unter Java 1.7 oder höher Die Standardmethode hierfür ist wie folgt:

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);

Siehe die entsprechende JavaDoc . Dieser Ansatz hat den Vorteil, dass keine explizite Initialisierung einer java.util.Random Instanz, die bei unsachgemäßer Verwendung zu Verwirrung und Fehlern führen kann.

Umgekehrt gibt es jedoch keine Möglichkeit, den Seed explizit zu setzen, so dass es schwierig sein kann, Ergebnisse in Situationen zu reproduzieren, in denen dies nützlich ist, z. B. beim Testen oder Speichern von Spielständen oder Ähnlichem. In solchen Situationen kann die unten gezeigte Technik aus der Zeit vor Java 1.7 verwendet werden.

Vor Java 1.7 Die Standardmethode hierfür ist wie folgt:

import java.util.Random;

/**
 * Returns a pseudo-random number between min and max, inclusive.
 * The difference between min and max can be at most
 * <code>Integer.MAX_VALUE - 1</code>.
 *
 * @param min Minimum value
 * @param max Maximum value.  Must be greater than min.
 * @return Integer between min and max, inclusive.
 * @see java.util.Random#nextInt(int)
 */
public static int randInt(int min, int max) {

    // NOTE: This will (intentionally) not run as written so that folks
    // copy-pasting have to think about how to initialize their
    // Random instance.  Initialization of the Random instance is outside
    // the main scope of the question, but some decent options are to have
    // a field that is initialized once and then re-used as needed or to
    // use ThreadLocalRandom (if using at least Java 1.7).
    // 
    // In particular, do NOT do 'Random rand = new Random()' here or you
    // will get not very good / not very random results.
    Random rand;

    // nextInt is normally exclusive of the top value,
    // so add 1 to make it inclusive
    int randomNum = rand.nextInt((max - min) + 1) + min;

    return randomNum;
}

Siehe die entsprechende JavaDoc . In der Praxis ist die java.util.Random Klasse ist oft vorzuziehen gegenüber [java.lang.Math.random()](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Math.html#random()) .

Insbesondere ist es nicht notwendig, das Rad der Zufallszahlengenerierung neu zu erfinden, wenn es eine unkomplizierte API in der Standardbibliothek gibt, um diese Aufgabe zu bewältigen.

48 Stimmen

Für Anrufe, bei denen max Wert ist Integer.MAX_VALUE kann es zu einem Überlauf kommen, der zu einem java.lang.IllegalArgumentException . Sie können es mit versuchen: randInt(0, Integer.MAX_VALUE) . Außerdem, wenn nextInt((max-min) + 1) den höchsten Wert zurückgibt (ziemlich selten, nehme ich an), wird er dann nicht wieder überlaufen (vorausgesetzt, min und max sind hoch genug)? Wie kann man mit dieser Art von Situationen umgehen?

0 Stimmen

Jetzt gibt es nextLong(long origin, long bound). Posting als Referenz. Ich bin mir nicht bewusst, ob es dort war, wenn asnwer für gebucht.

1510voto

TJ_Fischer Punkte 15663

Es ist zu beachten, dass dieser Ansatz stärker verzerrt und weniger effizient ist als ein nextInt Ansatz, https://stackoverflow.com/a/738651/360211

Ein Standardmuster für diese Aufgabe ist:

Min + (int)(Math.random() * ((Max - Min) + 1))

El Java Die mathematische Bibliotheksfunktion Math.random() erzeugt einen Doppelwert im Bereich [0,1) . Beachten Sie, dass dieser Bereich nicht die 1.

Um einen bestimmten Wertebereich zu erhalten, müssen Sie zunächst mit der Größe des Wertebereichs multiplizieren, den Sie abdecken möchten.

Math.random() * ( Max - Min )

Dies gibt einen Wert im Bereich [0,Max-Min) , wobei 'Max-Min' nicht enthalten ist.

Zum Beispiel, wenn Sie [5,10) müssen Sie fünf ganzzahlige Werte abdecken, also verwenden Sie

Math.random() * 5

Dies würde einen Wert im Bereich von [0,5) , wobei 5 nicht enthalten ist.

Nun müssen Sie diesen Bereich nach oben in den Bereich verschieben, den Sie anvisieren. Dazu fügen Sie den Wert Min hinzu.

Min + (Math.random() * (Max - Min))

Sie erhalten nun einen Wert im Bereich von [Min,Max) . In unserem Beispiel bedeutet das [5,10) :

5 + (Math.random() * (10 - 5))

Dies beinhaltet jedoch noch nicht Max und Sie erhalten einen doppelten Wert. Um den Max Wert enthalten, müssen Sie 1 zu Ihrem Bereichsparameter hinzufügen (Max - Min) und schneidet dann den Dezimalteil ab, indem er in eine int. Dies wird erreicht durch:

Min + (int)(Math.random() * ((Max - Min) + 1))

Und da haben Sie es. Ein zufälliger ganzzahliger Wert im Bereich [Min,Max] oder wie in diesem Beispiel [5,10] :

5 + (int)(Math.random() * ((10 - 5) + 1))

87 Stimmen

In der Sun-Dokumentation heißt es ausdrücklich, dass Sie besser Random() verwenden sollten, wenn Sie einen int benötigen, anstatt Math.random(), das einen double erzeugt.

7 Stimmen

Dies ist im Vergleich zu nextInt-Methoden tatsächlich voreingenommen stackoverflow.com/a/738651/360211

8 Stimmen

"Verzerrt" bedeutet in diesem Fall, dass nach 2^53 Durchläufen einige Zahlen im Durchschnitt ein zusätzliches Vorkommen haben werden.

459voto

Verwendung:

Random ran = new Random();
int x = ran.nextInt(6) + 5;

Die ganze Zahl x ist nun die Zufallszahl, die ein mögliches Ergebnis von 5-10 .

204voto

krosenvold Punkte 73093

Verwendung:

minimum + rn.nextInt(maxValue - minvalue + 1)

202voto

Alexis C. Punkte 87062

Mit java-8 führten sie die Methode ints(int randomNumberOrigin, int randomNumberBound) im Random Klasse.

Wenn Sie zum Beispiel fünf zufällige Ganzzahlen (oder eine einzige) im Bereich [0, 10] erzeugen wollen, tun Sie dies einfach:

Random r = new Random();
int[] fiveRandomNumbers = r.ints(5, 0, 11).toArray();
int randomNumber = r.ints(1, 0, 11).findFirst().getAsInt();

Der erste Parameter gibt nur die Größe der IntStream erzeugt (das ist die überladene Methode der Methode, die eine unbegrenzte IntStream ).

Wenn Sie mehrere separate Aufrufe durchführen müssen, können Sie einen unendlichen primitiven Iterator aus dem Stream erstellen:

public final class IntRandomNumberGenerator {

    private PrimitiveIterator.OfInt randomIterator;

    /**
     * Initialize a new random number generator that generates
     * random numbers in the range [min, max]
     * @param min - the min value (inclusive)
     * @param max - the max value (inclusive)
     */
    public IntRandomNumberGenerator(int min, int max) {
        randomIterator = new Random().ints(min, max + 1).iterator();
    }

    /**
     * Returns a random number in the range (min, max)
     * @return a random number in the range (min, max)
     */
    public int nextInt() {
        return randomIterator.nextInt();
    }
}

Sie können es auch tun für double y long Werte. Ich hoffe, es hilft! :)

3 Stimmen

Ich würde vorschlagen, dass Sie den randomIterator nur einmal instanziieren. Siehe Greg Case Kommentar zu seiner eigenen Antwort.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X