0에서 100 사이의 임의의 숫자를 얻으려고합니다.하지만 시퀀스에서 반복되지 않고 고유해야합니다. 예를 들어 5 개의 숫자를 얻었다면 82,12,53,64,32가되어야하고 82,12,53,12,32가 아니어야합니다. 저는 이것을 사용했지만 시퀀스에서 동일한 숫자를 생성합니다.
Random rand = new Random();
selected = rand.nextInt(100);
0에서 100 사이의 임의의 숫자를 얻으려고합니다.하지만 시퀀스에서 반복되지 않고 고유해야합니다. 예를 들어 5 개의 숫자를 얻었다면 82,12,53,64,32가되어야하고 82,12,53,12,32가 아니어야합니다. 저는 이것을 사용했지만 시퀀스에서 동일한 숫자를 생성합니다.
Random rand = new Random();
selected = rand.nextInt(100);
답변:
다음은 간단한 구현입니다. 이것은 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'인스턴스는 정확히 동일한 의사 난수 시퀀스를 반환합니다 .
참고 것을
public Integer(int value)생성자는deprecated자바 (9) 때문이다.
첫 번째 for 루프는 간단히 다음과 같이 변경할 수 있습니다.
for (int i = 1; i < 11; i++) {
list.add(i);
}
자바로 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);
Arrays#setAll()했으며 스트림보다 약간 빠릅니다. 그래서 :`Integer [] indices = new Integer [n]; Arrays.setAll (인덱스, i-> i); Collections.shuffle (Arrays.asList (indices)); return Arrays.stream (indices) .mapToInt (Integer :: intValue) .toArray (); `
long개별 비트에 액세스하기 위해 이동 및 마스크하는 위치 의 배열을 사용하여 쉽게 명확하게 부울 배열을 만들 수 있습니다 .)HashSet이미 생성 한 숫자를 저장하고 이미 해당 숫자를 생성 contains했는지 테스트 하는 데 사용 하는를 사용할 수 있습니다. 은 HashSet아마 부울 배열보다 약간 느릴 수 있지만, 메모리를 적게 차지합니다.
이 방법은 언급 할 가치가 있다고 생각합니다.
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);
}
}
SET_SIZE_REQUIRED충분히 큰은 (의 말을하자 더 이상 NUMBER_RANGE / 2당신은 훨씬 더 실행 시간을 예상되었다.
나는 이것을 그렇게 만들었다.
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 ~ 100 개의 숫자를 저장합니다.
1에서 100 사이의 난수를 위치로 생성하고 array [position-1]을 반환하여 값을 가져옵니다.
배열에서 숫자를 사용하면 값을 -1로 표시합니다 (이 숫자가 이미 사용되었는지 확인하기 위해 다른 배열을 유지할 필요가 없음).
배열의 값이 -1이면 임의의 숫자를 다시 가져와 배열의 새 위치를 가져옵니다.
나는이 문제에 대한 쉬운 해결책을 가지고있다. 이것으로 우리는 n 개의 고유 한 난수를 쉽게 생성 할 수있다. 그 논리는 누구나 어떤 언어로도 사용할 수있다.
for(int i=0;i<4;i++)
{
rn[i]= GenerateRandomNumber();
for (int j=0;j<i;j++)
{
if (rn[i] == rn[j])
{
i--;
}
}
}
이것을 시도
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);
}
}
값을 취하면 부울 배열을 사용하여 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;
}
}
}
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;
}
0에서 m-1까지의 숫자가 포함 된 목록을 상상해보십시오. 첫 번째 숫자를 선택하려면 간단히 rand.nextInt(m). 그런 다음 목록에서 번호를 제거하십시오. 이제 m-1 번호가 남아 있으므로rand.nextInt(m-1) . 우리가 얻은 숫자는 목록의 위치를 나타냅니다. 첫 번째 숫자보다 작 으면 첫 번째 숫자 이전의 목록 부분이 첫 번째 숫자를 제거해도 변경되지 않았으므로 두 번째 숫자입니다. 위치가 첫 번째 숫자보다 크거나 같으면 두 번째 숫자는 위치 +1입니다. 추가 유도를 수행하면이 알고리즘을 얻을 수 있습니다.
이 알고리즘은 O (n ^ 2) 복잡도를 가지고 있습니다. 따라서 큰 집합에서 소량의 고유 번호를 생성하는 데 좋습니다. 셔플 기반 알고리즘은 셔플을 수행하기 위해 최소한 O (m)가 필요합니다.
또한 셔플 기반 알고리즘은 셔플을 수행하기 위해 가능한 모든 결과를 저장하기 위해 메모리가 필요합니다.이 알고리즘은 필요하지 않습니다.
Collections 클래스를 사용할 수 있습니다.
Collections라는 유틸리티 클래스는 ArrayList와 같은 컬렉션에서 수행 할 수있는 다양한 작업을 제공합니다 (예 : 요소 검색, 최대 또는 최소 요소 찾기, 요소 순서 반전 등). 수행 할 수있는 작업 중 하나는 요소를 섞는 것입니다. 셔플은 각 요소를 목록의 다른 위치로 무작위로 이동합니다. Random 개체를 사용하여이를 수행합니다. 이것은 결정 론적 무작위성을 의미하지만 대부분의 상황에서 가능합니다.
ArrayList를 섞으려면 Collections 가져 오기를 프로그램 맨 위에 추가 한 다음 Shuffle 정적 메서드를 사용합니다. 배열 목록을 매개 변수로 셔플합니다.
import java.util.Collections;
import java.util.ArrayList;
public class Lottery {
public static void main(String[] args) {
//define ArrayList to hold Integer objects
ArrayList numbers = new ArrayList();
for(int i = 0; i < 100; i++)
{
numbers.add(i+1);
}
Collections.shuffle(numbers);
System.out.println(numbers);
}
}
오래된 스레드이지만 다른 옵션을 추가하면 해를 끼치 지 않을 수 있습니다. (JDK 1.8 람다 함수는 쉽게 만드는 것 같습니다.)
문제는 다음 단계로 나눌 수 있습니다.
다음은 몇 가지 설명이있는 함수입니다.
/**
* Provided an unsequenced / sequenced list of integers, the function returns unique random IDs as defined by the parameter
* @param numberToGenerate
* @param idList
* @return List of unique random integer values from the provided list
*/
private List<Integer> getUniqueRandomInts(List<Integer> idList, Integer numberToGenerate) {
List<Integer> generatedUniqueIds = new ArrayList<>();
Integer minId = idList.stream().mapToInt (v->v).min().orElseThrow(NoSuchElementException::new);
Integer maxId = idList.stream().mapToInt (v->v).max().orElseThrow(NoSuchElementException::new);
ThreadLocalRandom.current().ints(minId,maxId)
.filter(e->idList.contains(e))
.distinct()
.limit(numberToGenerate)
.forEach(generatedUniqueIds:: add);
return generatedUniqueIds;
}
따라서 'allIntegers'목록 객체에 대해 11 개의 고유 한 난수를 얻기 위해 다음과 같은 함수를 호출합니다.
List<Integer> ids = getUniqueRandomInts(allIntegers,11);
이 함수는 새로운 arrayList 'generatedUniqueIds'를 선언하고 반환하기 전에 필요한 숫자까지 각각의 고유 한 임의의 정수로 채 웁니다.
PS ThreadLocalRandom 클래스는 동시 스레드의 경우 공통 시드 값을 피합니다.
범위 또는 배열에서 고유 한 임의 값을 생성 하는 가장 간단한 방법입니다. 입니다.
이 예에서는 미리 정의 된 배열을 사용하지만이 방법을 적용하여 난수를 생성 할 수도 있습니다. 먼저 데이터를 검색 할 샘플 배열을 만듭니다.
ArrayList<Integer> sampleList = new ArrayList<>();
sampleList.add(1);
sampleList.add(2);
sampleList.add(3);
sampleList.add(4);
sampleList.add(5);
sampleList.add(6);
sampleList.add(7);
sampleList.add(8);
이제에서 sampleList고유 한 5 개의 난수를 생성합니다.
int n;
randomList = new ArrayList<>();
for(int i=0;i<5;i++){
Random random = new Random();
n=random.nextInt(8); //Generate a random index between 0-7
if(!randomList.contains(sampleList.get(n)))
randomList.add(sampleList.get(n));
else
i--; //reiterating the step
}
이것은 개념적으로 매우 간단합니다. 생성 된 임의의 값이 이미 존재하는 경우 단계를 반복합니다. 생성 된 모든 값이 고유 할 때까지 계속됩니다.
이 답변이 유용하다고 생각되면 다른 답변에 비해 개념이 훨씬 간단하므로 투표 할 수 있습니다 .
이것을 확인하십시오
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;
}
}
아래는 항상 고유 번호를 생성하는 데 사용한 방법입니다. 임의 함수는 숫자를 생성하고 텍스트 파일에 저장 한 다음 다음에 파일에서 검사 할 때이를 비교하고 새로운 고유 번호를 생성하므로 이러한 방식으로 항상 새로운 고유 번호가 있습니다.
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;
}
1..100있지만 (유명한 알고리즘이 있음) 첫 번째n요소 를 결정한 후에 중지 합니다.