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`.
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.
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))
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
.
Gebruik:
minimum + rn.nextInt(maxValue - minvalue + 1)
Met java-8 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! :)
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;
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