Criar sequência numérica aleatória sem repetição

Duplicado:

Números randoms únicos em O (1)?

Eu quero um gerador de números pseudo-randoms que pode gerar números sem repetições em uma ordem aleatória.

Por exemplo:

random (10)

pode retornar 5, 9, 1, 4, 2, 8, 3, 7, 6, 10

Existe uma maneira melhor de fazer isso além de fazer o intervalo de números e embaralhá-los ou checar a lista gerada por repetições?


Editar:

Também quero que seja eficiente na geração de grandes números sem o intervalo inteiro.


Editar:

Eu vejo todos sugerindo algoritmos randoms. Mas se eu quiser gerar um grande número random (1024 bytes +), esse método levaria muito mais memory do que se eu usasse um RNG regular e fosse inserido em um conjunto até que ele tivesse um comprimento especificado, certo? Não existe algoritmo matemático melhor para isso?

Você pode estar interessado em um registrador de deslocamento de feedback linear. Nós costumávamos criá-los com hardware, mas eu também os fazia em software. Ele usa um registrador de deslocamento com alguns dos bits xorados e alimentados de volta para a input, e se você escolher apenas os “toques” certos, você pode obter uma sequência que é tão longa quanto o tamanho do registro. Isto é, um lfsr de 16 bits pode produzir uma sequência de 65535 de comprimento sem repetições. É estatisticamente random, mas, claro, eminentemente repetível. Além disso, se for feito errado, você pode obter algumas sequências embaraçosamente curtas. Se você procurar o lfsr, você encontrará exemplos de como construí-los corretamente (isto é, “comprimento máximo”).

Um shuffle é uma maneira perfeitamente boa de fazer isso (desde que você não introduza um viés usando o algoritmo ingênuo). Veja o shuffle de Fisher-Yates .

Para garantir que a lista não se repita, teria que manter uma lista de números retornados anteriormente. Como é necessário, portanto, gerar a lista inteira até o final do algoritmo, isso é equivalente no requisito de armazenamento para gerar a lista ordenada e depois embaralhar.

Mais sobre embaralhar aqui: Criando uma lista ordenada aleatória a partir de uma lista ordenada

No entanto, se o intervalo dos números randoms for muito grande, mas a quantidade de números exigidos for pequena (você sugeriu que esse é o requisito real em um comentário), gere uma lista completa e embaralhe que é um desperdício. Um shuffle em um array enorme envolve acessar páginas de memory virtual de uma maneira que (por definição) derrota o sistema de paginação do sistema operacional (em menor escala, o mesmo problema ocorreria com o cache de memory da CPU).

Neste caso, pesquisar a lista até agora será muito mais eficiente. Assim, o ideal seria usar heurísticas (determinadas pelo experimento) para escolher a implementação correta para os argumentos dados. (Desculpas por dar exemplos em C # em vez de C ++, mas ASFAC ++ B estou treinando para pensar em C #).

IEnumerable GenerateRandomNumbers(int range, int quantity) { int[] a = new int[quantity]; if (range < Threshold) { for (int n = 0; n < range; n++) a[n] = n; Shuffle(a); } else { HashSet used = new HashSet(); for (int n = 0; n < quantity; n++) { int r = Random(range); while (!used.Add(r)) r = Random(range); a[n] = r; } } return a; } 

O custo de fazer a verificação de números repetidos, o looping enquanto houver colisões, etc., será caro, mas provavelmente haverá algum valor de Threshold onde ele se torna mais rápido do que alocar para toda a faixa.

Para requisitos de quantidade suficientemente pequena, pode ser mais rápido usar uma matriz para pesquisas lineares e used nele, devido à maior localização, menor sobrecarga, o baixo custo da comparação ...

Também para grandes quantidades E grandes intervalos, pode ser preferível retornar um object que produza os números na sequência sob solicitação, em vez de alocar a matriz para os resultados iniciais. Isso é muito fácil de implementar em C # graças à palavra-chave yield return :

 IEnumerable ForLargeQuantityAndRange(int quantity, int range) { for (int n = 0; n < quantity; n++) { int r = Random(range); while (!used.Add(r)) r = Random(range); yield return r; } } 

Se um número random é garantido para nunca repetir, não é mais random e a quantidade de aleatoriedade diminui à medida que os números são gerados (depois de nove números random(10) é bastante previsível e mesmo depois de apenas oito você tem 50% de chance).

Eu entendo que você não quer um shuffle para intervalos grandes, já que você teria que armazenar toda a lista para fazer isso.

Em vez disso, use um hash pseudo-random reversível. Em seguida, alimente os valores 0 1 2 3 4 5 6 etc por sua vez.

Há um número infinito de hashes como este. Eles não são muito difíceis de gerar se estiverem restritos a uma potência de 2, mas qualquer base pode ser usada.

Aqui está um que funcionaria, por exemplo, se você quisesse passar por todos os 2 32 32 valores de bit. É mais fácil escrever porque o implícito mod 2 ^ 32 da matemática inteira funciona a seu favor neste caso.

 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; } 

Se você não se importar com as propriedades de aleatoriedade medíocres e se o número de elementos permitir, você poderá usar um gerador de números randoms congruentes lineares .

Um shuffle é o melhor que você pode fazer para números randoms em um intervalo específico sem repetições. A razão pela qual o método que você descreve (gerar aleatoriamente números e colocá-los em um conjunto até atingir um tamanho especificado) é menos eficiente devido a duplicatas. Teoricamente, esse algoritmo pode nunca terminar. Na melhor das hipóteses, ele terminará em um período de tempo indeterminável, em comparação a um shuffle, que sempre será executado em uma quantidade de tempo altamente previsível.


Resposta a edições e comentários:

Se, como você indica nos comentários, o intervalo de números é muito grande e você deseja selecionar relativamente poucos deles aleatoriamente, sem repetições, então a probabilidade de repetições diminui rapidamente. Quanto maior a diferença de tamanho entre o intervalo e o número de seleções, menor a probabilidade de seleções repetidas e melhor será o desempenho do algoritmo de seleção e verificação descrito na pergunta.

Que tal usar o gerador de GUID (como em um no .net). Concedido, não é garantido que não haverá duplicatas, no entanto, a chance de obter um é bastante baixa.

Isso foi perguntado antes – veja minha resposta à pergunta anterior . Em poucas palavras: você pode usar uma cifra de bloco para gerar uma permutação segura (aleatória) sobre qualquer intervalo desejado, sem precisar armazenar toda a permutação em nenhum ponto.

Se você deseja criar números randoms grandes (digamos 64 bits ou mais) sem repetições, basta criá-los. Se você está usando um bom gerador de números randoms, que na verdade tem entropia suficiente, então as chances de gerar repetições são tão minúsculas que não vale a pena se preocupar.

Por exemplo, ao gerar chaves criptográficas, ninguém realmente se incomoda em verificar se elas geraram a mesma chave antes; já que você está confiando em seu gerador de números randoms que um invasor dedicado não conseguirá obter a mesma chave, então por que você esperaria que você tivesse a mesma chave acidentalmente?

Obviamente, se você tem um gerador de números randoms ruim (como a vulnerabilidade do gerador de números randoms SSL da Debian ), ou está gerando números suficientemente pequenos para que o paradoxo de aniversário lhe dê uma grande chance de colisão, você precisará fazer alguma coisa para garantir você não se repete. Mas para grandes números randoms com um bom gerador, apenas confie na probabilidade de não lhe dar nenhuma repetição.

Ao gerar seus números, use um filtro Bloom para detectar duplicatas. Isso usaria uma quantidade mínima de memory. Não haveria necessidade de armazenar números anteriores na série.

O trade off é que sua lista não pode ser exaustiva no seu alcance. Se os seus números são verdadeiramente da ordem de 256 ^ 1024, isso não é nada difícil.

(Claro que se eles são realmente randoms nessa escala, até mesmo se preocupar em detectar duplicatas é uma perda de tempo. Se cada computador na Terra gerasse um trilhão de números randoms com tamanho a cada segundo por trilhões de anos, a chance de uma colisão ainda é absolutamente insignificante.)

Eu respondo segundo gbarry sobre o uso de um LFSR . Eles são muito eficientes e simples de implementar, mesmo em software, e têm a garantia de não se repetir em (2 ^ N – 1) usos para um LFSR com um registro de deslocamento de N bits.

Existem algumas desvantagens: observando um pequeno número de saídas do RNG, pode-se reconstruir o LFSR e predizer todos os valores que ele irá gerar, tornando-os não utilizáveis ​​para criptografia e em qualquer lugar onde seja necessário um bom RNG. O segundo problema é que ou a palavra toda em zero ou toda a palavra (em termos de bits) é inválida dependendo da implementação do LFSR. A terceira questão que é relevante para a sua pergunta é que o número máximo gerado pelo LFSR é sempre uma potência de 2 – 1 (ou poder de 2 – 2).

A primeira desvantagem pode não ser um problema, dependendo do seu aplicativo. Do exemplo que você deu, parece que você não está esperando que o zero esteja entre as respostas; então, a segunda questão não parece relevante para o seu caso. O problema do valor máximo (e portanto do intervalo) pode ser resolvido reutilizando o LFSR até que você obtenha um número dentro do seu intervalo. Aqui está um exemplo:

Digamos que você queira ter números entre 1 e 10 (como no seu exemplo). Você usaria um LFSR de 4 bits que tenha um intervalo [1, 15] inclusive. Aqui está um pseudocódigo de como obter um número no intervalo [1,10]:

 x = LFSR.getRandomNumber(); while (x > 10) { x = LFSR.getRandomNumber(); } 

Você deve inserir o código anterior no seu RNG; para que o chamador não se importasse com a implementação. Observe que isso desaceleraria seu RNG se você usar um grande registro de deslocamento e o número máximo que você deseja não é uma potência de 2 – 1.

Shuffling N elementos não ocupa memory excessiva … pense nisso. Você só troca um elemento por vez, então a memory máxima usada é de N + 1.

Supondo que você tenha um gerador de números randoms ou pseudo-randoms, mesmo que não seja garantido retornar valores exclusivos, você pode implementar um que retorna valores exclusivos toda vez usando este código, assumindo que o limite superior permanece constante (ou seja, você sempre o chama com random(10) , e não o chamam de random(10); random(11) .

O código não verifica erros. Você pode adicionar você mesmo se quiser.
Também requer muita memory se você quiser um grande número de números.

 /* 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; } 

Suponha que você queira gerar uma série de 256 números randoms sem repetições.

  1. Criar um bloco de memory de 256 bits (32 bytes) inicializado com zeros, vamos chamá-lo
  2. Sua variável de loop será n , o número de números a serem gerados
  3. Loop de n = 256 para n = 1
  4. Gere um número random r no intervalo [0, n)
  5. Encontre o r zero bit zero em seu bloco de memory b , vamos chamá-lo de p
  6. Coloque p na sua lista de resultados, um array chamado q
  7. Inverta o p ésimo bit no bloco de memory b para 1
  8. Depois do n = 1 passe, você acaba de gerar sua lista de números

Aqui está um pequeno exemplo do que estou falando, usando n = 4 inicialmente:

 **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] 

Por favor, verifique as respostas em

Gerar sequência de inteiros em ordem aleatória sem construir toda a lista antecipadamente

e também minha resposta está lá como

  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. 

Eu fiz uma pergunta semelhante antes, mas o meu era para todo o intervalo de um int see Procurando por uma function Hash / Ordered Int / to / Shuffled Int /

 static std::unordered_set s; long l = 0; for(; !l && (s.end() != s.find(l)); l = generator()); v.insert(l); 

gerador () sendo seu gerador de números randoms. Você rola números contanto que a input não esteja no seu conjunto, então você adiciona o que você encontra nela. Você entendeu a ideia.

Eu fiz isso com muito tempo para o exemplo, mas você deve fazer um modelo se o seu PRNG for modelado.

Alternativa é usar um PRNG criptograficamente seguro que terá uma probabilidade muito baixa de gerar o dobro do mesmo número.

Se você não quer dizer propriedades de statistics baixas da sequência gerada, existe um método:

Digamos que você queira gerar N números, cada um com 1024 bits cada. Você pode sacrificar alguns bits do número gerado para ser “contador”.

Então você gera cada número random, mas em alguns bits você escolhe colocar contador codificado binário (da variável, você aumenta cada vez que o próximo número random é gerado).

Você pode dividir esse número em bits únicos e colocá-lo em alguns bits menos significativos do número gerado.

Dessa forma, você tem certeza de obter um número único a cada vez.

Quero dizer, por exemplo, que cada número gerado se parece com isso: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyxxxxyxyyyyxxyxx onde x é obtido diretamente do gerador e ys são retirados da variável do contador.

Mersenne twister

Descrição que pode ser encontrada aqui na Wikipedia: Mersenne twister

Olhe na parte inferior da página para implementações em vários idiomas.

O problema é selecionar uma sequência “aleatória” de N números únicos da faixa 1..M, onde não há restrição na relação entre N e M (M poderia ser muito maior, aproximadamente igual ou menor que N; eles podem não ser relativamente primos).

Expandindo a resposta do registrador de deslocamento de feedback linear: para um dado M, construa um LFSR máximo para a menor potência de dois que é maior que M. Então, pegue seus números do LFSR jogando números maiores que M. Em média, você irá jogue fora no máximo metade dos números gerados (já que por construção mais da metade do intervalo do LFSR é menor que M), então o tempo de execução esperado para obter um número é O (1). Você não está armazenando números gerados anteriormente, então o consumo de espaço também é O (1). Se você ciclar antes de obter N números, então M é menor que N (ou o LFSR é construído incorretamente).

Você pode encontrar os parâmetros para comprimento máximo de LFSRs até 168 bits aqui (da wikipedia): http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf

Aqui está um código java:

/ ** * Gera uma sequência de números “randoms” únicos em [0, M) * @author dkoes * * /

public class UniqueRandom {long lfsr; máscara longa; long max;

 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; } 

}

Esta resposta sugere algumas estratégias para obter o que você quer e garantir que eles estejam em uma ordem aleatória usando alguns algoritmos já conhecidos.

Existe uma versão de dentro para fora do algoritmo de embaralhamento da Fisher-Yates, chamado de versão de Durstenfeld, que distribui aleatoriamente itens sequencialmente adquiridos em matrizes e collections ao carregar o array ou coleção.

Uma coisa a lembrar é que o shuffle de Fisher-Yates (AKA Knuth) ou a versão de Durstenfeld usada no tempo de carregamento é altamente eficiente com matrizes de objects porque somente o ponteiro de referência para o object está sendo movido e o próprio object não precisa ser examinado ou comparado com qualquer outro object como parte do algoritmo.

Vou dar os dois algoritmos mais abaixo.

Se você quiser números randoms realmente grandes, na ordem de 1024 bytes ou mais, um gerador random realmente bom que possa gerar bytes não assinados ou palavras por vez será suficiente. Gerar aleatoriamente quantos bytes ou palavras você precisar para construir o número, transformá-lo em um object com um ponteiro de referência para ele e, ei, pronto, você tem um número inteiro random realmente enorme. Se você precisar de um intervalo específico realmente grande, você pode adicionar um valor base de zero bytes ao final de ordem baixa da seqüência de bytes para alterar o valor. Esta pode ser sua melhor opção.

Se você precisa eliminar duplicatas de números randoms realmente grandes, então isso é mais complicado. Mesmo com números randoms realmente enormes, a remoção de duplicatas também os torna significativamente tendenciosos e não randoms. Se você tem um conjunto realmente grande de números randoms realmente enormes e você seleciona aleatoriamente os que ainda não foram selecionados, então o viés é apenas o viés na criação de valores enormes para o enorme conjunto de números a partir do qual escolher. Uma versão reversa da versão de Durstenfeld do Yates-Fisher poderia ser usada para escolher aleatoriamente valores de um conjunto realmente grande deles, removê-los dos valores restantes a partir dos quais escolher e inseri-los em um novo array que é um subconjunto e poderia fazer isso apenas com as matrizes de origem e de destino in situ. Isso seria muito eficiente.

Isso pode ser uma boa estratégia para obter um pequeno número de números randoms com valores enormes de um conjunto muito grande deles em que eles não são duplicados. Basta escolher um local random no conjunto de origem, obter seu valor, trocar seu valor pelo elemento superior no conjunto de origem, reduzir o tamanho do conjunto de origem por um e repetir com o conjunto de fonts de tamanho reduzido até ter escolhido valores suficientes. Isto é essencial a versão de Durstenfeld de Fisher-Yates em sentido inverso. Você pode então usar a versão de Dursenfeld do algoritmo de Fisher-Yates para inserir os valores adquiridos no conjunto de destino. No entanto, isso é um exagero, uma vez que eles devem ser escolhidos aleatoriamente e ordenados aleatoriamente, como dado aqui.

Ambos os algoritmos assumem que você tem um método de instância numérica aleatória, nextInt (int setSize), que gera um inteiro random de zero para setSize, ou seja, há valores possíveis de setSize. Nesse caso, será o tamanho da matriz, pois o último índice da matriz é size-1.

O primeiro algoritmo é a versão de Durstenfeld do algoritmo de embaralhamento de Fisher-Yates (Knuth) aplicado a um array de comprimento arbitrário, que simplesmente posiciona números inteiros de 0 ao comprimento do array no array. A matriz não precisa ser uma matriz de inteiros, mas pode ser uma matriz de quaisquer objects que são adquiridos sequencialmente, o que, efetivamente, torna uma matriz de pointers de referência. É simples, curto e muito eficaz

 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, agora você tem uma matriz já randomizada.

Se você quiser aleatoriamente ordenar uma matriz que já possui, aqui está o algoritmo padrão de 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 

Para collections e conjuntos seqüenciados, ou seja, algum tipo de object de lista, você poderia simplesmente usar adds / ou inserts com um valor de índice que permite inserir itens em qualquer lugar, mas deve permitir adicionar ou append após o último item atual para evitar criar viés na randomização.

Aqui está uma maneira aleatória sem repetir os resultados. Também funciona para strings. É em C #, mas o logig deve funcionar em muitos lugares. Coloque os resultados randoms em uma lista e verifique se o novo elemento random está nessa lista. Se não, você tem um novo elemento random. Se estiver nessa lista, repita o random até obter um elemento que não esteja nessa lista.

 List Erledigte = new List(); 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; } } 

Para que uma sequência seja aleatória, não deve haver nenhuma correlação automática. A restrição que os números não devem repetir significa que o próximo número deve depender de todos os números anteriores, o que significa que não é mais random ….

Se você pode gerar números randoms ‘pequenos’, você pode gerar números randoms ‘grandes’ integrando-os: adicione um pequeno incremento random a cada ‘anterior’.

 const size_t amount = 100; // a limited amount of random numbers vector 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 ); 

As funções myshuffle e myshuffle eu generosamente delegam para outras pessoas 🙂

Na verdade, há um ponto menor a ser feito aqui; um gerador de números randoms que não é permitido repetir não é random.

para ter números randoms não repetidos e para evitar o tempo de cintura com a verificação de números duplos e obter novos números repetidamente, use o método abaixo que garantirá o uso mínimo de Rand: por exemplo, se você deseja obter 100 números randoms não repetidos: 1. preencha um array com números de 1 a 100 2. obtenha um número random usando a function Rand no intervalo de (1-100) 3. use o número random do genart como um índice para obter o valor do array (Numbers [IndexGeneratedFromRandFunction] 4 Desloque o número na matriz após esse índice para a esquerda 5. repita a partir do passo 2, mas agora o tocou deve ser (1-99) e continuar

agora temos um array com números diferentes!

 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; } }