반복실험 없이 난수 시퀀스 만들기
중복:
나는 무작위 순서로 반복 없이 숫자를 생성할 수 있는 의사 난수 생성기를 원합니다.
예:
무작위(10)
5, 9, 1, 4, 2, 8, 3, 7, 6, 10을 반환할 수 있습니다.
숫자의 범위를 만들어 섞거나 생성된 목록에서 반복을 확인하는 것 외에 더 좋은 방법이 있습니까?
편집:
또한 전체 범위 없이 큰 숫자를 생성하는 데 효율적이기를 원합니다.
편집:
모든 사람들이 셔플 알고리즘을 제안하는 것을 봅니다.하지만 만약 내가 큰 난수(1024바이트+)를 생성하고 싶다면, 그 방법은 일반 RNG를 사용하고 지정된 길이가 될 때까지 세트에 삽입하는 것보다 훨씬 더 많은 메모리가 필요할 것입니다, 그렇죠?이를 위한 더 나은 수학적 알고리즘은 없습니다.
선형 피드백 이동 레지스터에 관심이 있을 수 있습니다.우리는 이것들을 하드웨어로 만들곤 했지만, 저는 소프트웨어로도 만들었습니다.그것은 xored되고 입력으로 피드백되는 비트가 있는 시프트 레지스터를 사용합니다. 만약 당신이 올바른 "탭"을 선택한다면 레지스터 크기만큼 긴 시퀀스를 얻을 수 있습니다.즉, 16비트 lfsr은 반복 없이 65535 길이의 시퀀스를 생성할 수 있습니다.그것은 통계적으로 무작위적이지만 물론 매우 반복 가능합니다.또한, 만약 그것이 잘못되었다면, 여러분은 당황스러울 정도로 짧은 시퀀스를 얻을 수 있습니다.lfsr을 찾아보면 제대로 구성하는 방법(즉, "최대 길이")의 예를 찾을 수 있습니다.
이를 위한 완벽한 방법은 셔플입니다(순진 알고리즘을 사용하여 편향을 도입하지 않는 경우).피셔-예이츠 셔플을 참조하십시오.
임의의 숫자가 반복되지 않도록 보장되는 경우 더 이상 임의가 아니며 숫자가 생성됨에 따라 랜덤성의 양이 감소합니다(9개의 숫자 이후).random(10)
다소 예측 가능하며, 8회 이후에도 50-50의 확률이 있습니다.)
그렇게 하려면 전체 목록을 저장해야 하기 때문에 넓은 범위에 대한 셔플을 원하지 않는다는 것을 이해합니다.
대신 가역 유사 랜덤 해시를 사용합니다.그런 다음 0 1 2 3 4 5 6 등의 값을 차례로 입력합니다.
이와 같은 해시의 수는 무한합니다.2의 거듭제곱으로 제한된다면 생성하는 것은 어렵지 않지만, 어떤 염기라도 사용할 수 있습니다.
예를 들어, 2^3232비트 값을 모두 사용하려는 경우 다음과 같은 방법이 있습니다.이 경우 정수 연산의 암묵적 모드 2^32가 유리하기 때문에 쓰기가 가장 쉽습니다.
unsigned int reversableHash(unsigned int x)
{
x*=0xDEADBEEF;
x=x^(x>>17);
x*=0x01234567;
x+=0x88776655;
x=x^(x>>4);
x=x^(x>>9);
x*=0x91827363;
x=x^(x>>7);
x=x^(x>>11);
x=x^(x>>20);
x*=0x77773333;
return x;
}
보통 랜덤성 속성을 개의치 않고 원소의 수가 허용하는 경우 선형 합동 난수 생성기를 사용할 수 있습니다.
반복실험이 없는 특정 범위의 난수에 대해 할 수 있는 최선의 방법은 셔플입니다.설명하는 방법(숫자를 임의로 생성하여 지정된 길이에 도달할 때까지 집합에 저장)의 효율성이 떨어지는 이유는 중복 때문입니다.이론적으로, 그 알고리즘은 결코 끝나지 않을 수도 있습니다.항상 매우 예측 가능한 시간 내에 실행되는 셔플과 비교하여 기껏해야 결정할 수 없는 시간 내에 완료됩니다.
Response to edits and comments:
주석에 표시된 것처럼 숫자의 범위가 매우 크고 반복실험 없이 랜덤으로 비교적 적은 수의 반복실험을 선택하려는 경우 반복실험 가능성이 급격히 감소합니다.범위와 선택 항목 수 간의 크기 차이가 클수록 반복 선택 가능성이 작아지며, 질문에서 설명한 선택 및 확인 알고리즘의 성능이 향상됩니다.
의 GUID 제너레이터를 사용하는 것은 어떻습니까?NET). 중복이 없을 것이라는 보장은 없지만, 중복을 얻을 가능성은 상당히 낮습니다.
이전에 질문한 적이 있습니다. 이전 질문에 대한 답변을 참조하십시오.간단히 말해, 블록 암호를 사용하여 모든 지점에서 전체 순열을 저장할 필요 없이 원하는 범위에 걸쳐 안전한(임의의) 순열을 생성할 수 있습니다.
반복실험 없이 큰(예: 64비트 이상) 난수를 만들려면 반복실험 없이 그냥 만듭니다.만약 여러분이 충분한 엔트로피를 가진 좋은 난수 생성기를 사용한다면, 반복 생성의 가능성은 너무 작아서 걱정할 가치가 없습니다.
예를 들어, 암호화 키를 생성할 때 아무도 실제로 동일한 키를 생성한 적이 있는지 확인하는 데 신경 쓰지 않습니다. 전용 공격자가 동일한 키를 추출할 수 없을 것이라는 랜덤 번호 생성기를 신뢰하고 있는데, 실수로 동일한 키를 생성할 것이라고 예상하는 이유는 무엇입니까?
물론, Debian SSL 난수 생성기 취약성과 같은 잘못된 난수 생성기가 있거나 생일 역설이 충돌 가능성을 높일 정도로 작은 숫자를 생성하는 경우에는 실제로 반복이 발생하지 않도록 조치를 취해야 합니다.그러나 좋은 생성자가 있는 큰 난수의 경우 반복실험을 하지 않을 확률을 신뢰합니다.
숫자를 생성할 때 블룸 필터를 사용하여 중복 항목을 탐지합니다.이렇게 하면 최소한의 메모리를 사용할 수 있습니다.이전 숫자를 시리즈에 저장할 필요가 전혀 없습니다.
단점은 당신의 목록이 당신의 범위에서 전부일 수 없다는 것입니다.만약 당신의 숫자가 실제로 256^1024 정도라면, 그것은 전혀 절충이 되지 않습니다.
(물론 실제로 그 규모에서 무작위적인 경우 중복을 탐지하는 것조차 시간 낭비입니다.지구상의 모든 컴퓨터가 수조 년 동안 초당 크기가 되는 조 개의 무작위 숫자를 생성했다면, 충돌의 가능성은 여전히 절대적으로 무시할 수 있습니다.)
LFSR 사용에 대한 두 번째 답변입니다.이들은 소프트웨어에서도 매우 효율적이고 구현이 간단하며, N비트 시프트 레지스터가 있는 LFSR에 대해 (2^N - 1) 사용에서 반복되지 않도록 보장됩니다.
그러나 몇 가지 단점이 있습니다. RNG의 소수의 출력을 관찰함으로써 LFSR을 재구성하고 LFSR이 생성할 모든 값을 예측할 수 있으므로 암호화에 사용할 수 없고 좋은 RNG가 필요한 곳에서는 사용할 수 없습니다.두 번째 문제는 LFSR 구현에 따라 전체 0 워드 또는 전체 1 워드(비트 단위)가 유효하지 않다는 것입니다.질문과 관련된 세 번째 문제는 LFSR에서 생성되는 최대 수가 항상 2 - 1의 거듭제곱(또는 2 - 2의 거듭제곱)이라는 것입니다.
첫 번째 단점은 응용 프로그램에 따라 문제가 없을 수 있습니다.당신이 제시한 예를 보면, 당신은 0이 답 중에 포함되기를 기대하지 않는 것 같습니다. 따라서 두 번째 문제는 당신의 경우와 관련이 없어 보입니다.최대 값(따라서 범위) 문제는 사용자가 범위 내의 숫자를 얻을 때까지 LFSR을 재사용하여 해결할 수 있습니다.다음은 예입니다.
예를 들어 1에서 10 사이의 숫자를 사용한다고 가정합니다.[1, 15] 범위의 4비트 LFSR을 사용합니다.다음은 [1,10] 범위의 숫자를 가져오는 방법에 대한 유사 코드입니다.
x = LFSR.getRandomNumber();
while (x > 10) {
x = LFSR.getRandomNumber();
}
호출자가 구현에 대해 신경 쓰지 않도록 RNG에 이전 코드를 포함시켜야 합니다.큰 시프트 레지스터를 사용하고 원하는 최대 수가 2 - 1의 거듭제곱이 아닌 경우 RNG 속도가 느려집니다.
이 답변은 이미 잘 알려진 알고리즘을 사용하여 원하는 것을 얻고 임의의 순서로 정렬할 수 있는 몇 가지 전략을 제안합니다.
배열 또는 컬렉션을 로드하는 동안 순차적으로 획득한 항목을 배열 및 컬렉션으로 무작위로 배포하는 Durstenfeld 버전이라고 하는 Fisher-Yates 셔플 알고리즘의 내부 외부 버전이 있습니다.
한 가지 기억해야 할 것은 로드 시 사용되는 Fisher-Yates(일명 Knuth) 셔플 또는 Durstenfeld 버전이 객체 배열에서 매우 효율적이라는 것입니다. 객체에 대한 참조 포인터만 이동하고 객체 자체는 알고리즘의 일부로 다른 객체와 검사하거나 비교할 필요가 없기 때문입니다.
두 알고리즘 모두 아래에 자세히 설명하겠습니다.
1024바이트 이상의 엄청난 수의 난수를 원한다면 부호 없는 바이트나 단어를 한 번에 생성할 수 있는 정말 좋은 난수 생성기로 충분합니다.숫자를 구성하는 데 필요한 만큼의 바이트나 단어를 무작위로 생성하고, 숫자에 대한 참조 포인터를 사용하여 개체로 만듭니다. 그리고 여러분은 정말 큰 무작위 정수를 가지고 있습니다.특정한 매우 큰 범위가 필요한 경우 바이트 시퀀스의 하위 끝에 0바이트의 기본값을 추가하여 값을 위로 이동할 수 있습니다.이것이 최선의 선택일 수 있습니다.
만약 당신이 정말 큰 무작위 숫자의 중복을 제거해야 한다면, 그것은 더 까다롭습니다.정말 큰 난수를 사용하더라도 중복을 제거하면 상당히 편향되고 전혀 무작위적이지 않습니다.만약 여러분이 중복되지 않은 정말 큰 무작위 숫자들의 집합을 가지고 있고 아직 선택되지 않은 숫자들 중에서 무작위로 선택한다면, 편향은 단지 선택할 수 있는 정말 큰 숫자들의 집합에 대한 거대한 값들을 만드는 편향일 뿐입니다.Durstenfeld 버전의 Yates-Fisher는 매우 거대한 값 집합에서 값을 무작위로 선택하고, 나머지 값에서 값을 제거하여 하위 집합인 새 배열에 삽입할 수 있으며 소스 배열과 대상 배열만 배치하면 이 작업을 수행할 수 있습니다.이것은 매우 효율적일 것입니다.
이는 중복되지 않는 매우 큰 수의 랜덤 숫자 집합에서 엄청난 값을 갖는 소수의 랜덤 숫자를 얻는 데 좋은 전략이 될 수 있습니다.소스 세트에서 임의의 위치를 선택하고 값을 얻은 다음 해당 값을 소스 세트의 최상위 요소와 스왑하고 소스 세트의 크기를 1만큼 줄인 다음 충분한 값을 선택할 때까지 축소된 크기의 소스 세트를 반복합니다.이것은 본질적으로 더스텐펠트 버전의 피셔 예이츠 역입니다.그런 다음 Fisher-Yates 알고리즘의 Dursenfeld 버전을 사용하여 수집된 값을 대상 세트에 삽입할 수 있습니다.하지만, 여기에 주어진 대로 무작위로 선택하고 무작위로 주문해야 하기 때문에 그것은 과잉 살상입니다.
두 알고리즘 모두 0부터 setSize까지의 난수 정수를 생성하여 setSize 가능한 값이 있음을 의미하는 nextInt(intsetSize)라는 난수 인스턴스 메서드가 있다고 가정합니다.이 경우 배열에 대한 마지막 인덱스가 size-1이므로 배열의 크기가 됩니다.
첫 번째 알고리듬은 임의 길이의 배열에 적용되는 Fisher-Yates(일명 Knuth) 셔플 알고리듬의 더스텐펠트 버전으로, 0부터 배열 길이까지의 정수를 배열에 무작위로 배치합니다.배열이 정수 배열일 필요는 없지만, 사실상 참조 포인터 배열이 되는 순차적으로 획득되는 모든 개체의 배열일 수 있습니다.간단하고 짧으며 매우 효과적입니다.
int size = someNumber;
int[] int array = new int[size]; // here is the array to load
int location; // this will get assigned a value before used
// i will also conveniently be the value to load, but any sequentially acquired
// object will work
for (int i = 0; i <= size; i++) { // conveniently, i is also the value to load
// you can instance or acquire any object at this place in the algorithm to load
// by reference, into the array and use a pointer to it in place of j
int j = i; // in this example, j is trivially i
if (i == 0) { // first integer goes into first location
array[i] = j; // this may get swapped from here later
} else { // subsequent integers go into random locations
// the next random location will be somewhere in the locations
// already used or a new one at the end
// here we get the next random location
// to preserve true randomness without a significant bias
// it is REALLY IMPORTANT that the newest value could be
// stored in the newest location, that is,
// location has to be able to randomly have the value i
int location = nextInt(i + 1); // a random value between 0 and i
// move the random location's value to the new location
array[i] = array[location];
array[location] = j; // put the new value into the random location
} // end if...else
} // end for
Voila, 당신은 이미 무작위 배열을 가지고 있습니다.
이미 있는 배열을 임의로 섞으려면 표준 Fisher-Yates 알고리즘을 사용합니다.
type[] array = new type[size];
// some code that loads array...
// randomly pick an item anywhere in the current array segment,
// swap it with the top element in the current array segment,
// then shorten the array segment by 1
// just as with the Durstenfeld version above,
// it is REALLY IMPORTANT that an element could get
// swapped with itself to avoid any bias in the randomization
type temp; // this will get assigned a value before used
int location; // this will get assigned a value before used
for (int i = arrayLength -1 ; i > 0; i--) {
int location = nextInt(i + 1);
temp = array[i];
array[i] = array[location];
array[location] = temp;
} // end for
순서가 지정된 컬렉션 및 세트(예: 일부 유형의 목록 개체)의 경우 항목을 아무 곳에나 삽입할 수 있는 인덱스 값으로 추가/또는 삽입만 사용할 수 있지만, 랜덤화에서 편향이 발생하지 않도록 현재 마지막 항목 뒤에 추가하거나 추가할 수 있어야 합니다.
N개의 요소를 섞으면 과도한 메모리를 차지하지 않습니다...잘 생각해 보세요한 번에 하나의 요소만 스왑하므로 사용되는 최대 메모리는 N+1 요소의 메모리입니다.
또는 생성기가 할 때,을 반환하는 이 보장되지 이 코드를 하여 매번 고유한 할 수 임또유난생있가가유고, ▁it,▁call▁assuming▁generator,▁remains▁always▁limit▁with▁one-▁pseudo▁you가▁upper,i▁each이코유▁implement사일▁unique▁values▁assuming▁code 때마다 고유한 값을 반환하는 생성기를 구현할 수 있습니다(즉, 항상 로 호출).random(10)
그리고 그것으로 끝내지 마.random(10); random(11)
.
코드가 오류를 확인하지 않습니다.원하는 경우 직접 추가할 수 있습니다.
또한 큰 범위의 숫자를 원한다면 많은 메모리가 필요합니다.
/* the function returns a random number between 0 and max -1
* not necessarily unique
* I assume it's written
*/
int random(int max);
/* the function returns a unique random number between 0 and max - 1 */
int unique_random(int max)
{
static int *list = NULL; /* contains a list of numbers we haven't returned */
static int in_progress = 0; /* 0 --> we haven't started randomizing numbers
* 1 --> we have started randomizing numbers
*/
static int count;
static prev_max = 0;
// initialize the list
if (!in_progress || (prev_max != max)) {
if (list != NULL) {
free(list);
}
list = malloc(sizeof(int) * max);
prev_max = max;
in_progress = 1;
count = max - 1;
int i;
for (i = max - 1; i >= 0; --i) {
list[i] = i;
}
}
/* now choose one from the list */
int index = random(count);
int retval = list[index];
/* now we throw away the returned value.
* we do this by shortening the list by 1
* and replacing the element we returned with
* the highest remaining number
*/
swap(&list[index], &list[count]);
/* when the count reaches 0 we start over */
if (count == 0) {
in_progress = 0;
free(list);
list = 0;
} else { /* reduce the counter by 1 */
count--;
}
}
/* swap two numbers */
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
사실, 여기서 중요한 점이 있습니다. 반복해서는 안 되는 난수 생성기는 무작위가 아닙니다.
반복실험 없이 256개의 난수를 연속으로 생성하려고 합니다.
- 를 0이라고 합시다.
b
- 의 루프 는 루변수다같습니다과음이 될 입니다.
n
되지 않은 입니다. - 에서 루프
n = 256
n = 1
- 수생성난
r
범위내의[0, n)
- »
r
-0번째 비트b
끝내자꾸나p
- 다놓을 .
p
당의결목서록에과, 불배열는리라고라고 하는 .q
- 집기뒤를 .
p
비트 메모비블의 -트록리b
1
- 에
n = 1
되었습니다.
여기 제가 말하고 있는 것에 대한 짧은 예가 있습니다.n
처음에는 4개:
**Setup**
b = 0000
q = []
**First loop pass, where n = 4**
r = 2
p = 2
b = 0010
q = [2]
**Second loop pass, where n = 3**
r = 2
p = 3
b = 0011
q = [2, 3]
**Third loop pass, where n = 2**
r = 0
p = 0
b = 1011
q = [2, 3, 0]
** Fourth and final loop pass, where n = 1**
r = 0
p = 1
b = 1111
q = [2, 3, 0, 1]
다음에서 답변을 확인하십시오.
전체 목록을 미리 구성하지 않고 임의 순서로 정수 시퀀스 생성
그리고 또한 내 대답은 거기에 있습니다.
very simple random is 1+((power(r,x)-1) mod p) will be from 1 to p for values of x from 1 to p and will be random where r and p are prime numbers and r <> p.
전에도 비슷한 질문을 했지만, 제 질문은 전체 범위의 intee에 대한 것이었습니다. 해시 함수 찾기/주문된 Int/에서 /Shuffled Int/까지였습니다.
static std::unordered_set<long> s;
long l = 0;
for(; !l && (s.end() != s.find(l)); l = generator());
v.insert(l);
생성기는 임의의 숫자 생성기입니다.항목이 집합에 없는 한 숫자를 롤한 다음 해당 항목에서 찾은 내용을 추가합니다.당신은 이해합니다.
예시를 위해 길게 했는데, 당신의 PRNG가 템플릿화되었다면 당신은 그 템플릿을 만들어야 합니다.
대안은 두 배의 동일한 수를 생성할 확률이 매우 낮은 암호화 보안 PRNG를 사용하는 것입니다.
생성된 시퀀스의 모든 속성이 통계적으로 좋지 않다는 뜻이 아니라면 한 가지 방법이 있습니다.
각각 1024비트인 N개의 숫자를 생성하려고 합니다.생성된 숫자의 일부 비트를 "카운터"로 사용할 수 있습니다.
따라서 각 난수를 생성하지만 선택한 일부 비트에는 이진 인코딩 카운터를 배치합니다(변수에서 다음 난수가 생성될 때마다 증가함).
이 숫자를 하나의 비트로 나누고 생성된 숫자의 덜 중요한 비트에 넣을 수 있습니다.
그렇게 하면 매번 고유 번호를 얻을 수 있습니다.
예를 들어, 생성된 각 숫자는 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
메르센트위스터
다음에 대한 설명은 Wikipedia에서 찾을 수 있습니다.메르센트위스터
페이지 하단에서 다양한 언어로 구현된 내용을 확인합니다.
문제는 1 범위에서 N개의 고유 번호의 "랜덤" 시퀀스를 선택하는 것입니다.N과 M 사이의 관계에 제약이 없는 M(M은 N보다 훨씬 크거나 비슷하거나 더 작을 수 있으며 상대적으로 소수가 아닐 수 있음).
선형 피드백 이동 레지스터 답변에서 확장: 주어진 M에 대해 M보다 큰 2의 최소 거듭제곱에 대한 최대 LFSR을 구성합니다.그러면 LFSR에서 M보다 큰 숫자를 꺼내면 됩니다.평균적으로 생성된 숫자의 최대 절반을 폐기합니다(구조상 LFSR의 절반 이상 범위가 M보다 작기 때문에). 따라서 숫자를 얻는 예상 실행 시간은 O(1)입니다.이전에 생성된 숫자를 저장하고 있지 않으므로 공간 사용량도 O(1)입니다.N개의 숫자를 얻기 전에 사이클을 수행하면 M이 N보다 작거나 LFSR이 잘못 생성됩니다.
최대 길이 LFSR에 대한 매개 변수는 위키피디아에서 최대 168비트까지 찾을 수 있습니다.http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
다음은 몇 가지 Java 코드입니다.
* [0,M]에서 고유한 "랜덤" 숫자 시퀀스 생성 * @author dkoes */
공용 클래스 고유 랜덤 {long lfsr; 긴 마스크; 긴 최대값;
private static long seed = 1;
//indexed by number of bits
private static int [][] taps = {
null, // 0
null, // 1
null, // 2
{3,2}, //3
{4,3},
{5,3},
{6,5},
{7,6},
{8,6,5,4},
{9,5},
{10,7},
{11,9},
{12,6,4,1},
{13,4,3,1},
{14,5,3,1},
{15,14},
{16,15,13,4},
{17,14},
{18,11},
{19,6,2,1},
{20,17},
{21,19},
{22,21},
{23,18},
{24,23,22,17},
{25,22},
{26,6,2,1},
{27,5,2,1},
{28,25},
{29,27},
{30,6,4,1},
{31,28},
{32,22,2,1},
{33,20},
{34,27,2,1},
{35,33},
{36,25},
{37,5,4,3,2,1},
{38,6,5,1},
{39,35},
{40,38,21,19},
{41,38},
{42,41,20,19},
{43,42,38,37},
{44,43,18,17},
{45,44,42,41},
{46,45,26,25},
{47,42},
{48,47,21,20},
{49,40},
{50,49,24,23},
{51,50,36,35},
{52,49},
{53,52,38,37},
{54,53,18,17},
{55,31},
{56,55,35,34},
{57,50},
{58,39},
{59,58,38,37},
{60,59},
{61,60,46,45},
{62,61,6,5},
{63,62},
};
//m is upperbound; things break if it isn't positive
UniqueRandom(long m)
{
max = m;
lfsr = seed; //could easily pass a starting point instead
//figure out number of bits
int bits = 0;
long b = m;
while((b >>>= 1) != 0)
{
bits++;
}
bits++;
if(bits < 3)
bits = 3;
mask = 0;
for(int i = 0; i < taps[bits].length; i++)
{
mask |= (1L << (taps[bits][i]-1));
}
}
//return -1 if we've cycled
long next()
{
long ret = -1;
if(lfsr == 0)
return -1;
do {
ret = lfsr;
//update lfsr - from wikipedia
long lsb = lfsr & 1;
lfsr >>>= 1;
if(lsb == 1)
lfsr ^= mask;
if(lfsr == seed)
lfsr = 0; //cycled, stick
ret--; //zero is stuck state, never generated so sub 1 to get it
} while(ret >= max);
return ret;
}
}
다음은 결과를 반복하지 않고 랜덤화하는 방법입니다.그것은 또한 현악기에도 효과가 있습니다.C#에 있지만 로그는 여러 곳에서 작동해야 합니다.랜덤 결과를 목록에 넣고 새 랜덤 요소가 해당 목록에 있는지 확인합니다.그렇지 않은 경우 새 랜덤 요소가 있습니다.해당 목록에 있는 경우 해당 목록에 없는 요소를 얻을 때까지 랜덤을 반복합니다.
List<string> Erledigte = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = "";
listBox1.Items.Add("a");
listBox1.Items.Add("b");
listBox1.Items.Add("c");
listBox1.Items.Add("d");
listBox1.Items.Add("e");
}
private void button1_Click(object sender, EventArgs e)
{
Random rand = new Random();
int index=rand.Next(0, listBox1.Items.Count);
string rndString = listBox1.Items[index].ToString();
if (listBox1.Items.Count <= Erledigte.Count)
{
return;
}
else
{
if (Erledigte.Contains(rndString))
{
//MessageBox.Show("vorhanden");
while (Erledigte.Contains(rndString))
{
index = rand.Next(0, listBox1.Items.Count);
rndString = listBox1.Items[index].ToString();
}
}
Erledigte.Add(rndString);
label1.Text += rndString;
}
}
시퀀스가 랜덤인 경우에는 자동 상관 관계가 없어야 합니다.숫자가 반복되지 않아야 한다는 제한은 다음 숫자가 이전의 모든 숫자에 의존해야 한다는 것을 의미하며, 이는 더 이상 무작위가 아니라는 것을 의미합니다.
'작은' 난수를 생성할 수 있는 경우 '큰' 난수를 통합하여 생성할 수 있습니다. 즉, 각 '이전'에 작은 랜덤 증분을 추가할 수 있습니다.
const size_t amount = 100; // a limited amount of random numbers
vector<long int> numbers;
numbers.reserve( amount );
const short int spread = 250; // about 250 between each random number
numbers.push_back( myrandom( spread ) );
for( int n = 0; n != amount; ++n ) {
const short int increment = myrandom( spread );
numbers.push_back( numbers.back() + increment );
}
myshuffle( numbers );
그myrandom
그리고.myshuffle
이로써 나는 다른 사람들에게 아낌없이 위임하는 기능 :)
반복되지 않는 난수를 가지고 있고, 중복된 숫자를 확인하면서 허리에 걸리는 시간을 피하고 새로운 숫자를 반복적으로 얻기 위해서는 Rand의 최소 사용을 보장하는 아래의 방법을 사용합니다. 예를 들어, 100개의 비반복 난수를 얻고자 하는 경우: 1. 1에서 1002까지의 숫자로 배열을 채웁니다. Rand 함수를 사용하여 임의의 숫자를 얻습니다.(1-100)의 범위 3. 배열에서 th 값을 가져오기 위해 생성된 난수를 인덱스로 사용합니다(Numbers[IndexGeneratedFromRandFunction] 4. 해당 인덱스 뒤의 배열 번호를 왼쪽으로 이동 5. 2단계부터 반복하지만 이제 범위는 (1-99)이어야 합니다.
이제 우리는 다른 숫자를 가진 배열을 가지고 있습니다!
int main() {
int b[(the number
if them)];
for (int i = 0; i < (the number of them); i++) {
int a = rand() % (the number of them + 1) + 1;
int j = 0;
while (j < i) {
if (a == b[j]) {
a = rand() % (the number of them + 1) + 1;
j = -1;
}
j++;
}
b[i] = a;
}
}
언급URL : https://stackoverflow.com/questions/693880/create-random-number-sequence-with-no-repeats
'programing' 카테고리의 다른 글
Visual Studio Code - URI의 대상 'package:flutter/material.dart'가 없습니다. (0) | 2023.08.10 |
---|---|
도커 미승인: 인증 필요 - 성공적인 로그인과 함께 푸시 시 (0) | 2023.08.10 |
요소에 동일한 폭을 제공하지 않는 Flexbox (0) | 2023.08.10 |
MariaDB를 시작하고 센토스 기반 도커 이미지를 계속 실행하는 방법. (0) | 2023.08.10 |
재할당을 사용하여 할당된 메모리 축소 (0) | 2023.08.10 |