Vraag Hoe genereer ik willekeurige gehele getallen binnen een bepaald bereik in Java?


Hoe genereer ik een willekeurige int waarde in een specifiek bereik?

Ik heb het volgende geprobeerd, maar die werken niet:

Poging 1:

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

Poging 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`.

2897
2017-12-12 18:20


oorsprong


antwoorden:


In Java 1.7 of hoger, de standaardmanier om dit te doen is als volgt:

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);

Zien de relevante JavaDoc. Deze aanpak heeft het voordeel dat het niet nodig is om a. Expliciet te initialiseren java.util.Random Dit kan bijvoorbeeld een bron van verwarring en fouten zijn als het ongepast wordt gebruikt.

Omgekeerd is er echter geen manier om het zaad expliciet in te stellen, zodat het moeilijk kan zijn om resultaten te reproduceren in situaties waarin dat nuttig is, zoals het testen of opslaan van spelstatussen of iets dergelijks. In die situaties kan de onderstaande pre-Java 1.7-techniek worden gebruikt.

Voor Java 1.7, de standaardmanier om dit te doen is als volgt:

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;
}

Zien de relevante JavaDoc. In de praktijk is de java.util.Random klasse heeft vaak de voorkeur boven java.lang.Math.random ().

In het bijzonder is het niet nodig om het willekeurige integergeneratiewiel opnieuw uit te vinden wanneer er een eenvoudige API is binnen de standaardbibliotheek om de taak te volbrengen.


3254
2017-12-12 18:25



Merk op dat deze benadering meer vooringenomen en minder efficiënt is dan een nextInt nadering, https://stackoverflow.com/a/738651/360211

Een standaardpatroon om dit te bereiken is:

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

De Java Wiskundebibliotheekfunctie Math.random () genereert een dubbele waarde in het bereik [0,1). Merk op dat dit bereik niet de 1 omvat.

Om eerst een specifiek waardenbereik te krijgen, moet u vermenigvuldigen met de waarde van het bereik dat u wilt dekken.

Math.random() * ( Max - Min )

Hiermee wordt een waarde in het bereik geretourneerd [0,Max-Min), waarbij 'Max-Min' niet is inbegrepen.

Bijvoorbeeld, als je wilt [5,10), je moet vijf gehele waarden bedekken, zodat je ze gebruikt

Math.random() * 5

Dit zou een waarde in het bereik retourneren [0,5), waar 5 niet is inbegrepen.

Nu moet u dit bereik verplaatsen naar het bereik dat u target. U doet dit door de Min-waarde toe te voegen.

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

Je krijgt nu een waarde in het bereik [Min,Max). Naar ons voorbeeld volgen, dat betekent [5,10):

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

Maar dit omvat nog steeds niet Max en je krijgt een dubbele waarde. Om de Max waarde inbegrepen, moet u 1 toevoegen aan uw bereikparameter (Max - Min) en vervolgens het decimale gedeelte afkappen door naar een int te casten. Dit wordt bereikt via:

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

En daar heb je het. Een willekeurig geheel getal in het bereik [Min,Max], of per het voorbeeld [5,10]:

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

1323
2017-12-12 18:35



Gebruik:

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

Het gehele getal x is nu het willekeurige nummer met een mogelijke uitkomst 5-10.


311
2017-09-04 04:23



Gebruik:

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

122
2017-12-12 18:25



Met  zij introduceerden de methode ints(int randomNumberOrigin, int randomNumberBound) in de Random klasse.

Als je bijvoorbeeld vijf willekeurige gehele getallen (of één enkele) in het bereik [0, 10] wilt genereren, doe je gewoon:

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

De eerste parameter geeft alleen de grootte van de aan IntStream gegenereerd (wat de overbelaste methode is van degene die een onbeperkt produceert IntStream).

Als u meerdere afzonderlijke oproepen moet doen, kunt u een oneindige primitieve iterator uit de stream maken:

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();
    }
}

Je kunt het ook voor double en long waarden.

Hoop dat het helpt! :)


98
2017-11-26 18:29



U kunt uw voorbeeld van de tweede code bewerken in:

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

90
2017-12-12 18:31



Slechts een kleine aanpassing van uw eerste oplossing zou voldoende zijn.

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

Zie hier meer voor de implementatie van Random


89
2018-03-12 22:44