Правильный метод "статического" Random.Next в C#?
Зачем мне создавать экземпляр класса Random, если я хочу создать случайное число от 1 до 100 .... как
Random rand = new Random();
rand.Next(1,100);
Есть ли статическая функция класса Random, чтобы сделать то же самое? лайк...
Random.Next(1,100);
Я не хочу создавать экземпляр без необходимости
12 ответов
Лучше всего создать один экземпляр Random
и использовать его во всей вашей программе - иначе результаты могут быть не такими случайными. Такое поведение поощряется тем, что не создается статическая функция.
Вам не нужно беспокоиться о "создании экземпляра без необходимости", влияние в лучшем случае ничтожно мало - так работает фреймворк.
//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);
}
}
Это не "ненужно", потому что класс Random хранит некоторое состояние внутри. Это делает это, чтобы убедиться, что если вы позвоните .Next()
несколько раз очень быстро (за одну и ту же миллисекунду, тик или что-то еще) вы все равно не получите тот же номер.
Конечно, если это не проблема в вашем случае, вы всегда можете объединить эти две строки кода в одну:
new Random().Next(1, 100);
Вы уже получили ответы здесь. Просто повторяя правильное решение:
namespace mySpace
{
public static class Util
{
private static Random rnd = new Random();
public static int GetRandom()
{
return rnd.Next();
}
}
}
Так что вы можете позвонить:
var i = Util.GetRandom();
все на протяжении Если вам строго необходим статический метод без сохранения состояния для генерации случайных чисел, вы можете положиться на Guid
,
public static class Util
{
public static int GetRandom()
{
return Guid.NewGuid().GetHashCode();
}
}
Это будет немного медленнее, но может быть гораздо более случайным, чем Random.Next
По крайней мере, из моего опыта.
Но не:
new Random(Guid.NewGuid().GetHashCode()).Next();
Создание ненужного объекта замедлит работу, особенно в цикле.
И никогда:
new Random().Next();
Не только его медленнее (внутри цикла), но и случайность... ну, на мой взгляд, не очень хорошо..
Лучший способ сделать это - иметь ThreadStatic
Random
пример:
[ThreadStatic] static Random random;
Random Get() {
if (random == null) random = new Random(Guid.NewGuid().GetHashCode());
return random;
}
Это обо всем позаботится.
- Поток безопасности
- Спектакль
- Не нужно посеять
Это ускользает от меня, почему.NET Framework (и любой другой фреймворк на земле) не использует что-то в этом духе.
Из MSDN: Случайный класс (Система):
"Генерация случайного числа начинается с начального значения. Если одно и то же начальное число используется многократно, генерируется один и тот же ряд чисел. Один из способов получения различных последовательностей состоит в том, чтобы сделать начальное значение зависимым от времени, создавая тем самым разные серии с каждым новый экземпляр Random. По умолчанию конструктор без параметров класса Random использует системные часы для генерации своего начального значения, в то время как его параметризованный конструктор может принимать значение Int32 на основе количества тактов в текущем времени. Однако, поскольку часы имеет конечное разрешение, использование конструктора без параметров для создания различных случайных объектов в тесной последовательности создает генераторы случайных чисел, которые генерируют идентичные последовательности случайных чисел.В следующем примере показано, что два случайных объекта, которые создаются в тесной последовательности, генерируют идентичные серии случайных чисел..."
Создание нового экземпляра 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));
}
Даст вам лучшее распределение.
Почему бы и нет?
Вам нужно создать экземпляр, потому что случайные числа генерируются так, что предыдущие ответы влияют на последующие ответы. По умолчанию 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
Класс должен хранить данные экземпляра (предыдущий ответ или "начальное число") для последующих вызовов.
Создание недолговечного экземпляра в C# практически бесплатно. Не тратьте свое время на беспокойство по этому поводу. У вас, вероятно, есть лучшие места, где можно найти отличные результаты или увеличение памяти.
Генераторы случайных чисел должны поддерживать состояние, чтобы быть "случайным". Генератор случайных чисел создает последовательность, которая генерируется на основе случайного начального числа. Проблема в том, что в компьютере нет ничего случайного. Самая близкая вещь, которую компьютер имеет под рукой, - системные часы; это фактически время, в которое происходит процесс. Таким образом, по умолчанию используется текущий счетчик системных часов. Если ваше приложение достаточно быстрое, то при одном и том же системном тике может произойти много вычислений случайных чисел. Если генератор случайных чисел вообще не поддерживает состояние, он будет выдавать одно и то же случайное число несколько раз (один и тот же вход дает один и тот же выход). Обычно это не то, что вы хотите.
Я знаю, что он уже ответил, но я просто должен сказать, что я предпочитаю использовать шаблон синглтона в этом случае.
Я сделал один на:
http://www.codeproject.com/Tips/254057/Random-Color-Generator
Он использует цветовое расстояние CIELab (одно из лучших для человеческих глаз) для обеспечения легко различимых цветов. У него есть observableCollection цветов, которые вы хотите скрыть (например, задний цвет) плюс коэффициент расстояния (где 1 является значением по умолчанию).
Надеюсь, поможет...
Вам нужно что-то похожее на это, если вы хотите синтаксис, который вы упоминаете.
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);
без необходимости беспокоиться о посеве.