Правильный метод "статического" Random.Next в С#?
Почему мне нужно создать экземпляр класса Random, если я хочу создать случайное число от 1 до 100.... например
Random rand = new Random();
rand.Next(1,100);
Есть ли какая-либо статическая функция класса Random, чтобы сделать то же самое? как...
Random.Next(1,100);
Я не хочу создавать лишний экземпляр
Ответы
Ответ 1
Лучше всего создать один экземпляр Random
и использовать его во всей вашей программе, иначе результаты могут быть не такими случайными. Такое поведение рекомендуется, не создавая статическую функцию.
Вам не следует беспокоиться о том, что "создание экземпляра излишне", влияние в лучшем случае незначительно - так работает структура.
Ответ 2
//Function to get random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}
Скопировано непосредственно из
Ответ 3
Это не "лишний", потому что класс Random хранит некоторое состояние внутри. Он делает это, чтобы убедиться, что если вы вызываете .Next()
несколько раз очень быстро (в той же миллисекунде или тике или что-то еще), вы все равно не получите тот же номер.
Конечно, если это не проблема в вашем случае, вы всегда можете объединить эти две строки кода в один:
new Random().Next(1, 100);
Ответ 4
У вас уже есть ответы. Просто повторю правильное решение:
namespace mySpace
{
public static class Util
{
private static Random rnd = new Random();
public static int GetRandom()
{
return rnd.Next();
}
}
}
Итак, вы можете позвонить:
var i = Util.GetRandom();
. Если для генерации случайных чисел вам необходим только истинный статический метод stateless, вы можете положиться на Guid
.
public static class Util
{
public static int GetRandom()
{
return Guid.NewGuid().GetHashCode();
}
}
Это будет немного медленнее, но может быть намного более случайным, чем Random.Next
, по крайней мере, из моего опыта.
Но не:
new Random(Guid.NewGuid().GetHashCode()).Next();
Создание ненужного объекта сделает его медленнее, особенно в цикле.
И никогда:
new Random().Next();
Не только его медленнее (внутри цикла), это случайность... ну не очень хорошая по мне.
Ответ 5
От MSDN: Random Class (System):
"Генерация случайного числа начинается с начального значения. Если одно и то же семя используется повторно, генерируется одна и та же серия чисел. Один из способов создания разных последовательностей состоит в том, чтобы сделать начальное значение зависящим от времени, тем самым создавая другое серии с каждым новым экземпляром Random. По умолчанию конструктор без параметров в классе Random использует системные часы для генерации своего начального значения, тогда как его параметризованный конструктор может принимать значение Int32 в зависимости от количества тиков в текущий момент времени. Однако, поскольку часы имеют конечное разрешение, использование конструктора без параметров для создания разных случайных объектов с близкой последовательностью создает генераторы случайных чисел, которые производят идентичные последовательности случайных чисел. Следующий пример иллюстрирует, что два случайных объекта, которые создаются с близкой последовательностью, генерируют идентичный ряд случайных чисел..."
Википедия объясняет PRNG
Ответ 6
Почему бы и нет?
Вам нужно создать экземпляр, поскольку генерируются случайные числа, так как предыдущие ответы влияют на последующие ответы. По умолчанию конструктор new Random()
использует текущее системное время для "семени" последовательности, но ему не нужно: вы можете передать свой собственный номер, если хотите. В частности:
var rand = new Random(1234);
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Производит одну и ту же последовательность "случайных" чисел каждый раз.
Это означает, что класс Random
должен сохранять данные экземпляра (предыдущий ответ или "семя" ) для последующих вызовов.
Ответ 7
Создание нового экземпляра Random, вызывающего его сразу несколько раз, например:
for (int i = 0; i < 1000; i++)
{
Random rand = new Random();
Console.WriteLine(rand.Next(1,100));
}
Дает вам распределение, взвешенное в нижнем конце диапазона.
Выполнение этого способа:
Random rand = new Random();
for (int i = 0; i < 1000; i++)
{
Console.WriteLine(rand.Next(1,100));
}
Дайте вам лучшее распространение.
Ответ 8
Создание короткоживущего экземпляра на С# почти бесплатное. Не теряйте время, беспокоясь об этом. У вас, вероятно, есть лучшие места для поиска перфекционной или памяти.
Ответ 9
Лучший способ сделать это - иметь экземпляр ThreadStatic
Random
:
[ThreadStatic] static Random random;
Random Get() {
if (random == null) random = new Random(Guid.NewGuid().GetHashCode());
return random;
}
Это заботится обо всем.
- Безопасность потока
- Производительность
- Не нужно посеять
Это ускользает от меня, почему .NET Framework (и любая другая структура на земле) не использует что-то в этом духе.
Ответ 10
Я сделал одно:
http://www.codeproject.com/Tips/254057/Random-Color-Generator
Он использует расстояние цвета CIELab (одно из лучших для глаз человека), чтобы обеспечить легко различимые цвета. Он имеет наблюдаемый набор цветов, которые вы хотите сохранить (например, backcolor) плюс коэффициент расстояния (где 1 по умолчанию).
Надеюсь, что это поможет...
Ответ 11
Генераторы случайных чисел должны поддерживать состояние, чтобы быть "случайным". Генератор случайных чисел создает последовательность, которая генерируется на основе случайного семени. Проблема в том, что ничто в компьютере не является случайным. Самое близкое, что есть у компьютера - это системные часы; то есть эффективно время, в которое происходит процесс. Таким образом, по умолчанию используется текущий тиковый счетчик системных часов. Если ваше приложение достаточно быстро, многие вычисления случайных чисел могут возникать при одном и том же тике системы. Если генератор случайных чисел не поддерживает состояние вообще, он будет предоставлять одно и то же случайное число несколько раз (тот же ввод дает тот же результат). Обычно это не то, что вы хотите.
Я знаю, что он уже ответил, но я просто должен сказать, что я предпочитаю использовать шаблон singleton в этом случае.
Ответ 12
Вам нужно что-то подобное, если вы хотите указать указанный вами синтаксис.
namespace MyRandom
{
public class Random
{
private static m_rand = new Random();
public static Next(int min, int max)
{
return m_rand.Next(min, max);
}
}
}
Это должно позволить вам сделать Random.Next(1,100);
, не беспокоясь о посеве.