Programing

자바에서 고유 한 난수 생성

lottogame 2020. 10. 31. 09:09
반응형

자바에서 고유 한 난수 생성


0에서 100 사이의 임의의 숫자를 얻으려고합니다.하지만 시퀀스에서 반복되지 않고 고유해야합니다. 예를 들어 5 개의 숫자가 있으면 82,12,53,64,32가되어야하고 82,12,53,12,32가 아니어야합니다. 저는 이것을 사용했지만 시퀀스에서 동일한 숫자를 생성합니다.

Random rand = new Random();
selected = rand.nextInt(100);

  • 목록 구조 에서 범위의 각 숫자를 순차적으로 추가합니다 .
  • 셔플 하십시오.
  • 첫 번째 'n'을 가져옵니다.

다음은 간단한 구현입니다. 이것은 1-10 범위에서 3 개의 고유 한 난수를 인쇄합니다.

import java.util.ArrayList;
import java.util.Collections;

public class UniqueRandomNumbers {

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (int i=1; i<11; i++) {
            list.add(new Integer(i));
        }
        Collections.shuffle(list);
        for (int i=0; i<3; i++) {
            System.out.println(list.get(i));
        }
    }
}

Mark Byers가 현재 삭제 된 답변에서 지적했듯이 원래 접근 방식을 사용한 수정의 첫 번째 부분은 단일 Random인스턴스 만 사용하는 것 입니다.

그것이 숫자를 동일하게 만드는 원인입니다. Random예는 밀리 세컨드의 현재 시각에 의해 시드된다. 특정 시드 값의 경우 'random'인스턴스는 정확히 동일한 의사 난수 시퀀스를 반환합니다 .


자바로 8 + 당신이 사용할 수있는 ints방법을 Random얻기 위해 IntStream다음 임의 값을 distinct하고 limit고유 한 임의의 값의 번호로 스트림을 줄일 수 있습니다.

ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println);

Random또한 필요한 경우 LongStreams 및 DoubleStreams 를 만드는 메서드도 있습니다 .

임의의 순서로 범위의 모든 숫자 (또는 많은 양)를 원하는 경우 모든 숫자를 목록에 추가하고 섞은 다음 위의 예제가 현재 구현되어 있으므로 처음 n을 취하는 것이 더 효율적일 수 있습니다. 요청 된 범위에서 난수를 생성하고 집합을 통해 전달함으로써 ( Rob Kielty의 답변 과 유사 ), 새로운 고유 번호를 생성 할 확률이 발견 될 때마다 감소하기 때문에 제한에 전달 된 양보다 더 많이 생성해야 할 수 있습니다. 다른 방법의 예는 다음과 같습니다.

List<Integer> range = IntStream.range(0, 100).boxed()
        .collect(Collectors.toCollection(ArrayList::new));
Collections.shuffle(range);
range.subList(0, 99).forEach(System.out::println);

  1. 100 개의 숫자로 구성된 배열을 만든 다음 순서를 무작위로 지정합니다.
  2. 범위가 100 인 의사 난수 생성기를 고안하십시오.
  3. 100 개의 요소로 구성된 부울 배열을 만든 다음 해당 숫자를 선택할 때 요소를 true로 설정합니다. 다음 번호를 선택할 때 배열에 대해 확인하고 배열 요소가 설정되었는지 다시 시도하십시오. ( long개별 비트에 액세스하기 위해 이동 및 마스크하는 위치 의 배열을 사용하여 쉽게 명확하게 부울 배열을 만들 수 있습니다 .)

Collections.shuffle()100 개의 숫자를 모두 사용 하고 여기에 표시된대로 처음 5 개를 선택합니다 .


이 방법은 언급 할 가치가 있다고 생각합니다.

   private static final Random RANDOM = new Random();    
   /**
     * Pick n numbers between 0 (inclusive) and k (inclusive)
     * While there are very deterministic ways to do this,
     * for large k and small n, this could be easier than creating
     * an large array and sorting, i.e. k = 10,000
     */
    public Set<Integer> pickRandom(int n, int k) {
        final Set<Integer> picked = new HashSet<>();
        while (picked.size() < n) {
            picked.add(RANDOM.nextInt(k + 1));
        }
        return picked;
    }

나는 Anand의 대답을 리팩터링하여 Set의 고유 속성을 사용할뿐만 아니라 세트에 set.add()대한 추가가 실패 할 때 반환되는 부울 false도 사용했습니다 .

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class randomUniqueNumberGenerator {

    public static final int SET_SIZE_REQUIRED = 10;
    public static final int NUMBER_RANGE = 100;

    public static void main(String[] args) {
        Random random = new Random();

        Set set = new HashSet<Integer>(SET_SIZE_REQUIRED);

        while(set.size()< SET_SIZE_REQUIRED) {
            while (set.add(random.nextInt(NUMBER_RANGE)) != true)
                ;
        }
        assert set.size() == SET_SIZE_REQUIRED;
        System.out.println(set);
    }
}

나는 이것을 그렇게 만들었다.

    Random random = new Random();
    ArrayList<Integer> arrayList = new ArrayList<Integer>();

    while (arrayList.size() < 6) { // how many numbers u need - it will 6
        int a = random.nextInt(49)+1; // this will give numbers between 1 and 50.

        if (!arrayList.contains(a)) {
            arrayList.add(a);
        }
    }

이것은 고유 한 난수를 생성하는 데 작동합니다 ................

import java.util.HashSet;
import java.util.Random;

public class RandomExample {

    public static void main(String[] args) {
        Random rand = new Random();
        int e;
        int i;
        int g = 10;
        HashSet<Integer> randomNumbers = new HashSet<Integer>();

        for (i = 0; i < g; i++) {
            e = rand.nextInt(20);
            randomNumbers.add(e);
            if (randomNumbers.size() <= 10) {
                if (randomNumbers.size() == 10) {
                    g = 10;
                }
                g++;
                randomNumbers.add(e);
            }
        }
        System.out.println("Ten Unique random numbers from 1 to 20 are  : " + randomNumbers);
    }
}

이를 수행하는 한 가지 현명한 방법은 모듈러스에서 기본 요소의 지수를 사용하는 것입니다.

예를 들어, 2는 원시 루트 mod 101입니다. 즉, 2 mod 101의 거듭 제곱은 1에서 100까지의 모든 숫자를 표시하는 반복되지 않는 시퀀스를 제공합니다.

2^0 mod 101 = 1
2^1 mod 101 = 2
2^2 mod 101 = 4
...
2^50 mod 101 = 100
2^51 mod 101 = 99
2^52 mod 101 = 97
...
2^100 mod 101 = 1

Java 코드에서는 다음과 같이 작성합니다.

void randInts() {
int num=1;
for (int ii=0; ii<101; ii++) {
    System.out.println(num);
    num= (num*2) % 101;
    }
}

특정 계수에 대한 원시 루트를 찾는 것은 까다로울 수 있지만 Maple의 "primroot"기능이이를 수행합니다.


이 질문의 (중복되었습니다 또 다른 질문에서 이리가 자바에서 생성 고유 한 임의의 숫자 )

  1. 배열에 1 ~ 100 개의 숫자를 저장합니다.

  2. 1에서 100 사이의 난수를 위치로 생성하고 array [position-1]을 반환하여 값을 가져옵니다.

  3. 배열에서 숫자를 사용하면 값을 -1로 표시합니다 (이 숫자가 이미 사용되었는지 확인하기 위해 다른 배열을 유지할 필요가 없음).

  4. 배열의 값이 -1이면 임의의 숫자를 다시 가져와 배열의 새 위치를 가져옵니다.


이것을 시도

public class RandomValueGenerator {
    /**
     * 
     */
    private volatile List<Double> previousGenValues = new ArrayList<Double>();

    public void init() {
        previousGenValues.add(Double.valueOf(0));
    }

    public String getNextValue() {
        Random random = new Random();
        double nextValue=0;
        while(previousGenValues.contains(Double.valueOf(nextValue))) {
            nextValue = random.nextDouble();
        }
        previousGenValues.add(Double.valueOf(nextValue));
        return String.valueOf(nextValue);
    }
}

이것은 다른 답변과 크게 다르지 않지만 결국 정수 배열을 원했습니다.

    Integer[] indices = new Integer[n];
    Arrays.setAll(indices, i -> i);
    Collections.shuffle(Arrays.asList(indices));
    return Arrays.stream(indices).mapToInt(Integer::intValue).toArray();

아래는 항상 고유 번호를 생성하는 데 사용한 방법입니다. 임의 함수는 숫자를 생성하고 텍스트 파일에 저장 한 다음 다음에 파일에서 확인할 때이를 비교하고 새로운 고유 번호를 생성하므로 항상 새로운 고유 번호가 있습니다.

public int GenerateRandomNo()
{
    int _min = 0000;
    int _max = 9999;
    Random _rdm = new Random();
    return _rdm.Next(_min, _max);
}
public int rand_num()
{
    randnum = GenerateRandomNo();
    string createText = randnum.ToString() + Environment.NewLine;
    string file_path = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + @"\Invoices\numbers.txt";
    File.AppendAllText(file_path, createText);
    int number = File.ReadLines(file_path).Count(); //count number of lines in file
    System.IO.StreamReader file = new System.IO.StreamReader(file_path);
    do
    {
        randnum = GenerateRandomNo();
    }
    while ((file.ReadLine()) == randnum.ToString());
    file.Close();
    return randnum;

}

값을 취하면 부울 배열을 사용하여 true를 채울 수 있습니다. 그렇지 않으면 부울 배열을 통해 탐색하여 아래 주어진 값을 얻을 수 있습니다.

package study;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/*
Created By Sachin  Rane on Jul 18, 2018
*/
public class UniqueRandomNumber {
    static Boolean[] boolArray;
    public static void main(String s[]){
        List<Integer> integers = new ArrayList<>();


        for (int i = 0; i < 10; i++) {
            integers.add(i);
        }


        //get unique random numbers
        boolArray = new Boolean[integers.size()+1];
        Arrays.fill(boolArray, false);
        for (int i = 0; i < 10; i++) {
            System.out.print(getUniqueRandomNumber(integers) + " ");

        }

    }

    private static int  getUniqueRandomNumber(List<Integer> integers) {
        int randNum =(int) (Math.random()*integers.size());
        if(boolArray[randNum]){
            while(boolArray[randNum]){
                randNum++;
                if(randNum>boolArray.length){
                    randNum=0;
                }
            }
            boolArray[randNum]=true;
            return randNum;
        }else {
            boolArray[randNum]=true;
            return randNum;
        }

    }

}

나는이 문제에 대한 쉬운 해결책을 가지고있다. 이것으로 우리는 n 개의 고유 한 난수를 쉽게 생성 할 수있다. 그 논리는 누구나 어떤 언어로도 사용할 수있다.

for(int i=0;i<4;i++)
        {
            rn[i]= GenerateRandomNumber();
            for (int j=0;j<i;j++)
            {
                if (rn[i] == rn[j])
                {
                    i--;
                }
            }
        }

0부터 m-1까지 n 개의 고유 한 난수를 선택합니다.

int[] uniqueRand(int n, int m){
    Random rand = new Random();
    int[] r = new int[n];
    int[] result = new int[n];
    for(int i = 0; i < n; i++){
        r[i] = rand.nextInt(m-i);
        result[i] = r[i];
        for(int j = i-1; j >= 0; j--){
            if(result[i] >= r[j])
                result[i]++;
        }
    }
    return result;
}

Imagine a list containing numbers from 0 to m-1. To choose the first number, we simply use rand.nextInt(m). Then remove the number from the list. Now there remains m-1 numbers, so we call rand.nextInt(m-1). The number we get represents the position in the list. If it is less than the first number, then it is the second number, since the part of list prior to the first number wasn't changed by the removal of the first number. If the position is greater than or equal to the first number, the second number is position+1. Do some further derivation, you can get this algorithm.

Explanation

This algorithm has O(n^2) complexity. So it is good for generating small amount of unique numbers from a large set. While the shuffle based algorithm need at least O(m) to do the shuffle.

Also shuffle based algorithm need memory to store every possible outcome to do the shuffle, this algorithm doesn’t need.


Check this

public class RandomNumbers {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int n = 5;
        int A[] = uniqueRandomArray(n);
        for(int i = 0; i<n; i++){
            System.out.println(A[i]);
        }
    }
    public static int[] uniqueRandomArray(int n){
        int [] A = new int[n];
        for(int i = 0; i< A.length; ){
            if(i == A.length){
                break;
            }
            int b = (int)(Math.random() *n) + 1;
            if(f(A,b) == false){
                A[i++] = b;
            } 
        }
        return A;
    }
    public static boolean f(int[] A, int n){
        for(int i=0; i<A.length; i++){
            if(A[i] == n){
                return true;
            }
        }
        return false;
    }
}

참고URL : https://stackoverflow.com/questions/8115722/generating-unique-random-numbers-in-java

반응형