Создание случайных, уникальных значений С#
Я искал некоторое время и пытался найти это, я пытаюсь сгенерировать несколько случайных, уникальных чисел С#. Я использую System.Random
, и я использую семя DateTime.Now.Ticks
:
public Random a = new Random(DateTime.Now.Ticks.GetHashCode());
private void NewNumber()
{
MyNumber = a.Next(0, 10);
}
Я регулярно звоню в NewNumber()
, но проблема в том, что я часто получаю повторные номера. Некоторые люди предложили, потому что я объявлял случайное число каждый раз, когда я делал это, оно не получало бы случайное число, поэтому я поместил объявление вне своей функции. Любые предложения или лучшие способы, чем использование System.Random
? Спасибо
Ответы
Ответ 1
Я регулярно звоню в NewNumber(), но проблема в том, что я часто получаю повторные номера.
Random.Next
не гарантирует уникальность числа. Также ваш диапазон от 0 до 10, и, скорее всего, вы получите повторяющиеся значения. Возможно, вы можете настроить список int
и вставить случайные числа в список после проверки, не содержит ли он дубликата. Что-то вроде:
public Random a = new Random(); // replace from new Random(DateTime.Now.Ticks.GetHashCode());
// Since similar code is done in default constructor internally
public List<int> randomList = new List<int>();
int MyNumber = 0;
private void NewNumber()
{
MyNumber = a.Next(0, 10);
if (!randomList.Contains(MyNumber))
randomList.Add(MyNumber);
}
Ответ 2
Вы можете попробовать перетасовать массив возможных int, если ваш диапазон составляет всего от 0 до 9. Это добавляет преимущество избежания конфликтов в генерации чисел.
var nums = Enumerable.Range(0, 10).ToArray();
var rnd = new Random();
// Shuffle the array
for (int i = 0;i < nums.Length;++i)
{
int randomIndex = rnd.Next(nums.Length);
int temp = nums[randomIndex];
nums[randomIndex] = nums[i];
nums[i] = temp;
}
// Now your array is randomized and you can simply print them in order
for (int i = 0;i < nums.Length;++i)
Console.WriteLine(nums[i]);
Ответ 3
ПРИМЕЧАНИЕ. Я не рекомендую это:).
Здесь также "oneliner":
//This code generates numbers between 1 - 100 and then takes 10 of them.
var result = Enumerable.Range(1,101).OrderBy(g => Guid.NewGuid()).Take(10).ToArray();
Ответ 4
Я отправляю правильную реализацию алгоритма перетасовки, так как другая, размещенная здесь, не создает равномерного тасования.
Как утверждается в другом ответе, для небольшого числа значений, которые должны быть рандомизированы, вы можете просто заполнить массив этими значениями, перетасовать массив и затем использовать любое количество значений, которые вы хотите.
Ниже приведена реализация Fisher-Yates Shuffle (также известный как Knuth Shuffle). (Прочитайте раздел "Ошибки реализации" этой ссылки (найдите "всегда выбирайте j из всего диапазона допустимых индексов массива на каждой итерации" ), чтобы посмотреть, как это происходит с другой версией, размещенной здесь.)
using System;
using System.Collections.Generic;
namespace ConsoleApplication2
{
static class Program
{
static void Main(string[] args)
{
Shuffler shuffler = new Shuffler();
List<int> list = new List<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
shuffler.Shuffle(list);
foreach (int value in list)
{
Console.WriteLine(value);
}
}
}
/// <summary>Used to shuffle collections.</summary>
public class Shuffler
{
/// <summary>Creates the shuffler with a <see cref="MersenneTwister"/> as the random number generator.</summary>
public Shuffler()
{
_rng = new Random();
}
/// <summary>Shuffles the specified array.</summary>
/// <typeparam name="T">The type of the array elements.</typeparam>
/// <param name="array">The array to shuffle.</param>
public void Shuffle<T>(IList<T> array)
{
for (int n = array.Count; n > 1; )
{
int k = _rng.Next(n);
--n;
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
private System.Random _rng;
}
}
Ответ 5
Проверьте этот готовый к использованию метод: укажите диапазон и количество чисел, которое вы хотите получить.
public static int[] getUniqueRandomArray(int min, int max, int count) {
int[] result = new int[count];
List<int> numbersInOrder = new List<int>();
for (var x = min; x < max; x++) {
numbersInOrder.Add(x);
}
for (var x = 0; x < count; x++) {
var randomIndex = Random.Range(0, numbersInOrder.Count);
result[x] = numbersInOrder[randomIndex];
numbersInOrder.RemoveAt(randomIndex);
}
return result;
}
Ответ 6
В зависимости от того, что вы действительно после того, как вы можете сделать что-то вроде этого:
using System;
using System.Collections.Generic;
using System.Linq;
namespace SO14473321
{
class Program
{
static void Main()
{
UniqueRandom u = new UniqueRandom(Enumerable.Range(1,10));
for (int i = 0; i < 10; i++)
{
Console.Write("{0} ",u.Next());
}
}
}
class UniqueRandom
{
private readonly List<int> _currentList;
private readonly Random _random = new Random();
public UniqueRandom(IEnumerable<int> seed)
{
_currentList = new List<int>(seed);
}
public int Next()
{
if (_currentList.Count == 0)
{
throw new ApplicationException("No more numbers");
}
int i = _random.Next(_currentList.Count);
int result = _currentList[i];
_currentList.RemoveAt(i);
return result;
}
}
}
Ответ 7
И вот моя версия поиска N случайных уникальных чисел с использованием HashSet.
Выглядит довольно просто, поскольку HashSet может содержать только разные элементы.
Это интересно - было бы быстрее, чем использовать List или Shuffler?
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class RnDHash
{
static void Main()
{
HashSet<int> rndIndexes = new HashSet<int>();
Random rng = new Random();
int maxNumber;
Console.Write("Please input Max number: ");
maxNumber = int.Parse(Console.ReadLine());
int iter = 0;
while (rndIndexes.Count != maxNumber)
{
int index = rng.Next(maxNumber);
rndIndexes.Add(index);
iter++;
}
Console.WriteLine("Random numbers were found in {0} iterations: ", iter);
foreach (int num in rndIndexes)
{
Console.WriteLine(num);
}
Console.ReadKey();
}
}
}
Ответ 8
Я отметил, что принятый ответ продолжает добавлять int в список и продолжает проверять их с помощью if (!randomList.Contains(MyNumber))
и я думаю, что это плохо масштабируется, особенно если вы продолжаете запрашивать новые номера.
Я бы сделал наоборот.
- Генерация списка при запуске, линейно
- Получить случайный индекс из списка
- Удалить найденный int из списка
Это потребует немного больше времени при запуске, но будет гораздо лучше масштабироваться.
public class RandomIntGenerator
{
public Random a = new Random();
private List<int> _validNumbers;
private RandomIntGenerator(int desiredAmount, int start = 0)
{
_validNumbers = new List<int>();
for (int i = 0; i < desiredAmount; i++)
_validNumbers.Add(i + start);
}
private int GetRandomInt()
{
if (_validNumbers.Count == 0)
{
//you could throw an exception here
return -1;
}
else
{
var nextIndex = a.Next(0, _validNumbers.Count - 1);
var number = _validNumbers[nextIndex];
_validNumbers.RemoveAt(nextIndex);
return number;
}
}
}
Ответ 9
Вы также можете использовать dataTable, сохраняя каждое случайное значение, а затем просто выполняйте случайный метод while!= values в dataColumn
Ответ 10
Функция randomNumber возвращает необработанное целочисленное значение в диапазоне от 0 до 100000
bool check[] = new bool[100001];
Random r = new Random();
public int randomNumber() {
int num = r.Next(0,100000);
while(check[num] == true) {
num = r.Next(0,100000);
}
check[num] = true;
return num;
}
Ответ 11
привет, здесь я разместил одно видео, и оно объясняет, как генерировать уникальное случайное число
public List<int> random_generator(){
Random random = new Random();
List<int> random_container = new List<int>;
do{
int random_number = random.next(10);
if(!random_container.contains(random_number){
random_container.add(random_number)
}
}
while(random_container.count!=10);
return random_container;
}
здесь ,, в случайном контейнере вы получите не повторяющиеся 10 чисел, начиная с 0 до 9 (10 чисел), как случайные.. спасибо........
Ответ 12
Вы можете использовать базовые случайные функции С#
Random ran = new Random();
int randomno = ran.Next(0,100);
теперь вы можете использовать значение в случайном порядке во всем, что хотите, но имейте в виду, что это приведет к случайному числу между 0
и 100
Only, и вы можете расширить его до любой цифры.
Ответ 13
Попробуйте следующее:
private void NewNumber()
{
Random a = new Random(Guid.newGuid().GetHashCode());
MyNumber = a.Next(0, 10);
}
Некоторые объяснения:
Guid
: база здесь: представляет глобально уникальный идентификатор (GUID)
Guid.newGuid()
создает уникальный идентификатор типа "936DA01F-9ABD-4d9d-80C7-02AF85C822A8"
и он будет уникальным во всем мире здесь
Хэш-код здесь выдает уникальное целое из нашего уникального идентификатора
поэтому Guid.newGuid().GetHashCode()
дает нам уникальное число, и случайный класс будет генерировать реальные случайные числа, бросая это