Я использую .NET для создания программы искусственной жизни, и я использую псевдослучайный класс C #, определенный в Singleton. Идея состоит в том, что, если я буду использовать один и тот же генератор случайных чисел во всем приложении, я мог бы просто сохранить начальное значение и затем перезагрузить начальное значение для повторного вычисления определенного интересного прогона.
public sealed class RandomNumberGenerator : Random
{
private static readonly RandomNumberGenerator instance = new RandomNumberGenerator();
RandomNumberGenerator()
{
}
public static RandomNumberGenerator Instance
{
get
{
return instance;
}
}
}
Я также хотел метод, который мог бы дать мне два разных случайных числа.
public static Tuple<int, int> TwoDifferentRandomNumbers(this Random rnd, int minValue, int maxValue)
{
if (minValue >= maxValue)
throw new ArgumentOutOfRangeException("maxValue", "maxValue must be greater than minValue");
if (minValue + 1 == maxValue)
return Tuple.Create<int, int>(minValue, maxValue);
int rnd1 = rnd.Next(minValue, maxValue);
int rnd2 = rnd.Next(minValue, maxValue);
while (rnd1 == rnd2)
{
rnd2 = rnd.Next(minValue, maxValue);
}
return Tuple.Create<int, int>(rnd1, rnd2);
}
Проблема в том, что иногда rnd.Next(minValue,maxValue
всегда возвращает minValue
. Если в этой точке я остановлюсь и попытаюсь создать двойное значение и установить его на rnd.NextDouble()
, он вернет 0.0. Кто-нибудь знает, почему это происходит?
Я знаю, что это генератор псевдослучайных чисел, но, честно говоря, я не ожидал, что он заблокируется на 0. Доступ к генератору случайных чисел осуществляется из нескольких потоков ... Может ли это быть источником проблемы?
РЕДАКТИРОВАТЬ: Спасибо, проблема в том, что поток безопасности.
Это новая версия класса.
public sealed class RandomNumberGenerator : Random
{
private static Random _global = new Random();
[ThreadStatic]
private static Random _localInstance;
RandomNumberGenerator()
{
}
public static Random Instance
{
get
{
Random inst = _localInstance;
if (inst == null)
{
int seed;
lock (_global) seed = _global.Next();
_localInstance = inst = new Random(seed);
}
return _localInstance;
}
}
}