이 경우 MAX가 5에 불과하므로 중복을 하나씩 확인할 수 있지만 어떻게하면 더 간단하게 할 수 있을까요? 예를 들어 MAX의 값이 20이면 어떻게됩니까? 감사.
int MAX = 5;
for (i = 1 , i <= MAX; i++)
{
drawNum[1] = (int)(Math.random()*MAX)+1;
while (drawNum[2] == drawNum[1])
{
drawNum[2] = (int)(Math.random()*MAX)+1;
}
while ((drawNum[3] == drawNum[1]) || (drawNum[3] == drawNum[2]) )
{
drawNum[3] = (int)(Math.random()*MAX)+1;
}
while ((drawNum[4] == drawNum[1]) || (drawNum[4] == drawNum[2]) || (drawNum[4] == drawNum[3]) )
{
drawNum[4] = (int)(Math.random()*MAX)+1;
}
while ((drawNum[5] == drawNum[1]) ||
(drawNum[5] == drawNum[2]) ||
(drawNum[5] == drawNum[3]) ||
(drawNum[5] == drawNum[4]) )
{
drawNum[5] = (int)(Math.random()*MAX)+1;
}
}
답변
가장 간단한 방법은 가능한 숫자 목록 (1..20 또는 기타)을 만든 다음 Collections.shuffle
. 그런 다음 원하는 많은 요소를 선택하십시오. 범위가 마지막에 필요한 요소의 수와 같을 때 유용합니다 (예 : 카드 더미를 섞는 경우).
1..10,000 범위에서 임의의 요소 10 개를 원하면 그렇게 잘 작동하지 않습니다. 불필요하게 많은 작업을 수행하게됩니다. 이 시점에서 지금까지 생성 한 값 세트를 유지하고 다음 값이 아직 없을 때까지 루프에서 숫자를 계속 생성하는 것이 좋습니다.
if (max < numbersNeeded)
{
throw new IllegalArgumentException("Can't ask for more numbers than are available");
}
Random rng = new Random(); // Ideally just create one instance globally
// Note: use LinkedHashSet to maintain insertion order
Set<Integer> generated = new LinkedHashSet<Integer>();
while (generated.size() < numbersNeeded)
{
Integer next = rng.nextInt(max) + 1;
// As we're adding to a set, this will automatically do a containment check
generated.add(next);
}
하지만 세트 선택에 LinkedHashSet
주의하세요. 여기에서 신경 쓰는 삽입 순서를 유지하므로 매우 고의적으로 사용 했습니다.
또 다른 옵션은 매번 범위를 줄이고 기존 값을 보완 하여 항상 진행하는 것입니다. 예를 들어 0..9 범위에서 3 개의 값을 원한다고 가정합니다. 첫 번째 반복에서 0..9 범위의 숫자를 생성합니다. 4를 생성한다고 가정 해 보겠습니다.
두 번째 반복에서 0..8 범위의 숫자를 생성합니다. 생성 된 숫자가 4보다 작 으면 그대로 유지합니다. 그렇지 않으면 하나를 추가합니다. 4가없는 0..9의 결과 범위를 얻습니다. 그런 식으로 7을 얻는다고 가정합니다.
세 번째 반복에서 0..7 범위의 숫자를 생성합니다. 생성 된 숫자가 4보다 작 으면 그대로 유지합니다. 4 또는 5 인 경우 하나를 추가합니다. 6 또는 7이면 2 개를 더합니다. 이렇게하면 결과 범위는 4 또는 6이없는 0..9입니다.
답변
방법은 다음과 같습니다.
import java.util.ArrayList;
import java.util.Random;
public class Test {
public static void main(String[] args) {
int size = 20;
ArrayList<Integer> list = new ArrayList<Integer>(size);
for(int i = 1; i <= size; i++) {
list.add(i);
}
Random rand = new Random();
while(list.size() > 0) {
int index = rand.nextInt(list.size());
System.out.println("Selected: "+list.remove(index));
}
}
}
존경 씨 스키트는 지적 아웃이 있기 때문에 :
만약을 n 개의 무작위로 선택된 번호의 수를 당신이 선택하고자하는 N 선택할 수있는 번호의 전체 표본 공간입니다 :
- 만약 N << N , 당신은 당신이 선택했음을 번호를 저장하고 선택한 번호가 거기에 있는지 목록을 확인해야합니다.
- 경우 N ~ = N은 , 당신은 아마 전체 샘플 공간을 포함하는 목록을 채우고 다음을 선택로에서 숫자를 제거하여 내 방법을 사용해야합니다.
답변
//random numbers are 0,1,2,3
ArrayList<Integer> numbers = new ArrayList<Integer>();
Random randomGenerator = new Random();
while (numbers.size() < 4) {
int random = randomGenerator .nextInt(4);
if (!numbers.contains(random)) {
numbers.add(random);
}
}
답변
LFSR을 사용하여 “무작위”주문 번호를 수행하는 또 다른 방법이 있습니다. 다음을 살펴보십시오.
http://en.wikipedia.org/wiki/Linear_feedback_shift_register
이 기술을 사용하면 인덱스별로 정렬 된 난수를 얻고 값이 중복되지 않도록 할 수 있습니다.
그러나 랜덤 생성이 결정적이기 때문에 이들은 TRUE 난수가 아닙니다.
그러나 경우에 따라이 기술을 사용하여 셔플 링을 사용할 때 난수 생성 처리량을 줄일 수 있습니다.
여기 자바의 LFSR 알고리즘 (기억하지 않는 곳에서 가져 왔습니다) :
public final class LFSR {
private static final int M = 15;
// hard-coded for 15-bits
private static final int[] TAPS = {14, 15};
private final boolean[] bits = new boolean[M + 1];
public LFSR() {
this((int)System.currentTimeMillis());
}
public LFSR(int seed) {
for(int i = 0; i < M; i++) {
bits[i] = (((1 << i) & seed) >>> i) == 1;
}
}
/* generate a random int uniformly on the interval [-2^31 + 1, 2^31 - 1] */
public short nextShort() {
//printBits();
// calculate the integer value from the registers
short next = 0;
for(int i = 0; i < M; i++) {
next |= (bits[i] ? 1 : 0) << i;
}
// allow for zero without allowing for -2^31
if (next < 0) next++;
// calculate the last register from all the preceding
bits[M] = false;
for(int i = 0; i < TAPS.length; i++) {
bits[M] ^= bits[M - TAPS[i]];
}
// shift all the registers
for(int i = 0; i < M; i++) {
bits[i] = bits[i + 1];
}
return next;
}
/** returns random double uniformly over [0, 1) */
public double nextDouble() {
return ((nextShort() / (Integer.MAX_VALUE + 1.0)) + 1.0) / 2.0;
}
/** returns random boolean */
public boolean nextBoolean() {
return nextShort() >= 0;
}
public void printBits() {
System.out.print(bits[M] ? 1 : 0);
System.out.print(" -> ");
for(int i = M - 1; i >= 0; i--) {
System.out.print(bits[i] ? 1 : 0);
}
System.out.println();
}
public static void main(String[] args) {
LFSR rng = new LFSR();
Vector<Short> vec = new Vector<Short>();
for(int i = 0; i <= 32766; i++) {
short next = rng.nextShort();
// just testing/asserting to make
// sure the number doesn't repeat on a given list
if (vec.contains(next))
throw new RuntimeException("Index repeat: " + i);
vec.add(next);
System.out.println(next);
}
}
}
답변
당신은 당신이 원하는 얼마나 많은 숫자를 지정할 수 있습니다 또 다른 방법 size
과 min
및 max
반환 된 숫자의 값
public static int getRandomInt(int min, int max) {
Random random = new Random();
return random.nextInt((max - min) + 1) + min;
}
public static ArrayList<Integer> getRandomNonRepeatingIntegers(int size, int min,
int max) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
while (numbers.size() < size) {
int random = getRandomInt(min, max);
if (!numbers.contains(random)) {
numbers.add(random);
}
}
return numbers;
}
사용하려면 0에서 25 사이의 7 개의 숫자를 반환합니다.
ArrayList<Integer> list = getRandomNonRepeatingIntegers(7, 0, 25);
for (int i = 0; i < list.size(); i++) {
System.out.println("" + list.get(i));
}
답변
이것은 다음에서 훨씬 더 간단합니다 java-8
.
Stream.generate(new Random()::ints)
.distinct()
.limit(16) // whatever limit you might need
.toArray(Integer[]::new);
답변
반복되지 않는 난수를 갖는 가장 효율적이고 기본적인 방법은이 의사 코드로 설명됩니다. 중첩 된 루프 또는 해시 된 조회가 필요하지 않습니다.
// get 5 unique random numbers, possible values 0 - 19
// (assume desired number of selections < number of choices)
const int POOL_SIZE = 20;
const int VAL_COUNT = 5;
declare Array mapping[POOL_SIZE];
declare Array results[VAL_COUNT];
declare i int;
declare r int;
declare max_rand int;
// create mapping array
for (i=0; i<POOL_SIZE; i++) {
mapping[i] = i;
}
max_rand = POOL_SIZE-1; // start loop searching for maximum value (19)
for (i=0; i<VAL_COUNT; i++) {
r = Random(0, max_rand); // get random number
results[i] = mapping[r]; // grab number from map array
mapping[r] = max_rand; // place item past range at selected location
max_rand = max_rand - 1; // reduce random scope by 1
}
첫 번째 반복이 시작하기 위해 난수 3을 생성했다고 가정합니다 (0-19). 그러면 결과 [0] = 매핑 [3], 즉 값 3이됩니다. 그런 다음 매핑 [3]을 19에 할당합니다.
다음 반복에서 난수는 5 (0-18)였습니다. 그러면 결과 [1] = mapping [5], 즉 값 5가됩니다. 그런 다음 mapping [5]를 18에 할당합니다.
이제 다음 반복이 다시 3을 선택했다고 가정합니다 (0-17). results [2]에는 mapping [3]의 값이 할당되지만 이제이 값은 3이 아니라 19입니다.
이 동일한 보호 기능은 동일한 숫자를 연속으로 5 번 얻더라도 모든 숫자에 대해 유지됩니다. 예를 들어, 난수 생성기가 0을 연속으로 5 번 주면 결과는 [0, 19, 18, 17, 16]이됩니다.
같은 숫자를 두 번 얻지 못할 것입니다.