zufallszahlen - java zufallszahl zwischen zwei zahlen




Wie generiere ich Zufallszahlen in einem bestimmten Bereich in Java? (20)

Ab Java 7 sollten Sie Random nicht mehr verwenden. Für die meisten ThreadLocalRandom ist ThreadLocalRandom der Zufallszahlengenerator der Wahl.

Verwenden SplittableRandom für Fork-Join-Pools und parallele Streams SplittableRandom .

Joshua Bloch. Effektives Java. Dritte Edition.

Beginnend mit Java 8

Verwenden SplittableRandom für Fork-Join-Pools und parallele Streams SplittableRandom , das normalerweise schneller ist und im Vergleich zu Random eine bessere statistische Unabhängigkeit und Einheitlichkeit aufweist.

So generieren Sie ein zufälliges int im Bereich [0, 1_000]:

int n = new SplittableRandom().nextInt(0, 1_001);

So erzeugen Sie ein zufälliges int[100] [0, 1_000]: von Werten im Bereich [0, 1_000]:

int[] a = new SplittableRandom().ints(100, 0, 1_001).parallel().toArray();

So geben Sie einen Stream mit zufälligen Werten zurück:

IntStream stream = new SplittableRandom().ints(100, 0, 1_001);

Wie generiere ich einen zufälligen int Wert in einem bestimmten Bereich?

Ich habe folgendes versucht, aber das funktioniert nicht:

Versuch 1:

randomNum = minimum + (int)(Math.random() * maximum);
// Bug: `randomNum` can be bigger than `maximum`.

Versuch 2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;
// Bug: `randomNum` can be smaller than `minimum`.

Beachten Sie, dass dieser Ansatz voreingenommener und weniger effizient ist als ein nextInt Ansatz ( https://.com/a/738651/360211

Ein Standardmuster dafür ist:

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

Die Java Math-Bibliotheksfunktion Math.random () generiert einen doppelten Wert im Bereich [0,1) . Beachten Sie, dass dieser Bereich nicht die 1 umfasst.

Um zunächst einen bestimmten Wertebereich zu erhalten, müssen Sie die 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.

Wenn Sie zum Beispiel [5,10) möchten, müssen Sie fünf ganzzahlige Werte abdecken, damit Sie diese verwenden können

Math.random() * 5

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

Nun müssen Sie diesen Bereich auf den Zielbereich verschieben, auf den Sie abzielen. Dazu fügen Sie den Min-Wert hinzu.

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

Sie erhalten jetzt einen Wert im Bereich [Min,Max) . Nach unserem Beispiel bedeutet das [5,10) :

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

Dies schließt jedoch immer noch nicht Max und Sie erhalten einen doppelten Wert. Um den Max Wert zu erhalten, müssen Sie den Range-Parameter (Max - Min) um 1 erhöhen und dann den Dezimalteil durch Umwandeln in ein int abschneiden. Dies wird erreicht durch:

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

Und da hast du es. Ein zufälliger ganzzahliger Wert im Bereich [Min,Max] oder gemäß dem Beispiel [5,10] :

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

Benutzen:

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

Das können Sie in Java 8 prägnant erreichen:

Random random = new Random();

int max = 10;
int min = 5;
int totalNumber = 10;

IntStream stream = random.ints(totalNumber, min, max);
stream.forEach(System.out::println);

Diese Methoden sind möglicherweise bequem zu verwenden:

Diese Methode gibt eine Zufallszahl zwischen dem angegebenen Mindest- und Höchstwert zurück:

public static int getRandomNumberBetween(int min, int max) {
    Random foo = new Random();
    int randomNumber = foo.nextInt(max - min) + min;
    if (randomNumber == min) {
        // Since the random number is between the min and max values, simply add 1
        return min + 1;
    } else {
        return randomNumber;
    }
}

und diese Methode gibt eine Zufallszahl aus dem angegebenen Min- und Max-Wert zurück (die generierte Zahl könnte auch die Min- oder Max-Zahl sein):

public static int getRandomNumberFrom(int min, int max) {
    Random foo = new Random();
    int randomNumber = foo.nextInt((max + 1) - min) + min;

    return randomNumber;
}

Eine andere Option ist nur die Verwendung von Apache Commons :

import org.apache.commons.math.random.RandomData;
import org.apache.commons.math.random.RandomDataImpl;

public void method() {
    RandomData randomData = new RandomDataImpl();
    int number = randomData.nextInt(5, 10);
    // ...
 }

Es ist besser, SecureRandom anstelle von Random zu verwenden.

public static int generateRandomInteger(int min, int max) {
    SecureRandom rand = new SecureRandom();
    rand.setSeed(new Date().getTime());
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}

Hier ein einfaches Beispiel, das zeigt, wie eine Zufallszahl aus dem geschlossenen Bereich [min, max] generiert wird, während min <= max is true

Sie können es als Feld in der Random.class wiederverwenden, wobei alle Random.class Methoden an einem Ort vorhanden sind

Ergebnisbeispiel:

RandomUtils random = new RandomUtils();
random.nextInt(0, 0); // returns 0
random.nextInt(10, 10); // returns 10
random.nextInt(-10, 10); // returns numbers from -10 to 10 (-10, -9....9, 10)
random.nextInt(10, -10); // throws assert

Quellen:

import junit.framework.Assert;
import java.util.Random;

public class RandomUtils extends Random {

    /**
     * @param min generated value. Can't be > then max
     * @param max generated value
     * @return values in closed range [min, max].
     */
    public int nextInt(int min, int max) {
        Assert.assertFalse("min can't be > then max; values:[" + min + ", " + max + "]", min > max);
        if (min == max) {
            return max;
        }

        return nextInt(max - min + 1) + min;
    }
}


Ich habe dieses Beispiel gefunden. Zufallszahlen generieren :

In diesem Beispiel werden zufällige Ganzzahlen in einem bestimmten Bereich generiert.

import java.util.Random;

/** Generate random integers in a certain range. */
public final class RandomRange {

  public static final void main(String... aArgs){
    log("Generating random integers in the range 1..10.");

    int START = 1;
    int END = 10;
    Random random = new Random();
    for (int idx = 1; idx <= 10; ++idx){
      showRandomInteger(START, END, random);
    }

    log("Done.");
  }

  private static void showRandomInteger(int aStart, int aEnd, Random aRandom){
    if ( aStart > aEnd ) {
      throw new IllegalArgumentException("Start cannot exceed End.");
    }
    //get the range, casting to long to avoid overflow problems
    long range = (long)aEnd - (long)aStart + 1;
    // compute a fraction of the range, 0 <= frac < range
    long fraction = (long)(range * aRandom.nextDouble());
    int randomNumber =  (int)(fraction + aStart);    
    log("Generated : " + randomNumber);
  }

  private static void log(String aMessage){
    System.out.println(aMessage);
  }
} 

Ein Beispiellauf dieser Klasse:

Generating random integers in the range 1..10.
Generated : 9
Generated : 3
Generated : 3
Generated : 9
Generated : 4
Generated : 1
Generated : 3
Generated : 9
Generated : 10
Generated : 10
Done.

In Java 1.7 oder höher lautet die Standardmethode 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 das entsprechende JavaDoc . Dieser Ansatz hat den Vorteil, dass eine Instanz von java.util.Random nicht explizit initialisiert werden muss, was bei unsachgemäßer Verwendung zu Verwirrung und Fehlern führen kann.

Umgekehrt gibt es jedoch keine Möglichkeit, den Startwert explizit festzulegen, sodass es schwierig sein kann, Ergebnisse in Situationen zu reproduzieren, in denen dies nützlich ist, z. B. das Testen oder Speichern von Spielzuständen oder Ähnlichem. In diesen Situationen kann die unten gezeigte vor Java 1.7-Technik verwendet werden.

Vor Java 1.7 ist dies standardmäßig so:

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 das entsprechende JavaDoc . In der Praxis ist die Klasse java.util.Random häufig java.lang.Math.random() vorzuziehen.

Insbesondere ist es nicht erforderlich, das Rad für die Erzeugung von Zufallszahlen ganz neu zu erfinden, wenn sich in der Standardbibliothek eine einfache API befindet, um die Aufgabe auszuführen.


Mit java-8 wurde die Methode ints(int randomNumberOrigin, int randomNumberBound) in der Random Klasse eingeführt.

Wenn Sie beispielsweise fünf zufällige Ganzzahlen (oder eine einzelne) im Bereich [0, 10] generieren möchten, tun Sie einfach Folgendes:

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 des erzeugten IntStream (die überladene Methode der Methode, die einen unbegrenzten IntStream ).

Wenn Sie mehrere separate Aufrufe ausfü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 dies auch für double und long Werte tun.

Ich hoffe es hilft! :)


Nur eine kleine Modifikation Ihrer ersten Lösung würde ausreichen.

Random rand = new Random();
randomNum = minimum + rand.nextInt((maximum - minimum) + 1);

Weitere Informationen zur Implementierung von Random


Sie können Ihr zweites Codebeispiel bearbeiten, um:

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

Verwenden Sie einfach die Random Klasse:

Random ran = new Random();
// Assumes max and min are non-negative.
int randomInt = min + ran.nextInt(max - min + 1);

Verzeihen Sie mir bitte, dass Sie anspruchsvoll sind, aber die von der Mehrheit vorgeschlagene Lösung, dh min + rng.nextInt(max - min + 1)) , scheint gefährlich zu sein, weil:

  • rng.nextInt(n) kann Integer.MAX_VALUE nicht erreichen.
  • (max - min) kann zu einem Überlauf führen, wenn min negativ ist.

Eine narrensichere Lösung würde korrekte Ergebnisse für ein beliebiges Integer.MIN_VALUE min <= max innerhalb von [ Integer.MIN_VALUE , Integer.MAX_VALUE ] zurückgeben. Betrachten Sie die folgende naive Implementierung:

int nextIntInRange(int min, int max, Random rng) {
   if (min > max) {
      throw new IllegalArgumentException("Cannot draw random int from invalid range [" + min + ", " + max + "].");
   }
   int diff = max - min;
   if (diff >= 0 && diff != Integer.MAX_VALUE) {
      return (min + rng.nextInt(diff + 1));
   }
   int i;
   do {
      i = rng.nextInt();
   } while (i < min || i > max);
   return i;
}

Obwohl dies ineffizient ist, ist zu beachten, dass die Erfolgswahrscheinlichkeit in der while Schleife immer 50% oder mehr beträgt.


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


 rand.nextInt((max+1) - min) + min;

private static Random random = new Random();    

public static int getRandomInt(int min, int max){
  return random.nextInt(max - min + 1) + min;
}

ODER

public static int getRandomInt(Random random, int min, int max)
{
  return random.nextInt(max - min + 1) + min;
}

public static Random RANDOM = new Random(System.nanoTime());

public static final float random(final float pMin, final float pMax) {
    return pMin + RANDOM.nextFloat() * (pMax - pMin);
}




integer