2011-01-31 2 views
10

Возможные Дубликаты:
c# - getting the same random number repeatedly
Random number generator not working the way I had planned (C#)Генерация случайных чисел - то же число возвращается

У меня есть метод, который строит очередь Интс:

public Queue<int> generateTrainingInts(int count = 60) 
    { 
     Queue<int> retval = new Queue<int>(); 

     for (int i = 0; i < count; i++) 
     { 
      retval.Enqueue(JE_Rand.rInt(2001, 100)); 
     } 

     return retval; 
    } 

JE_Rand .rInt() - это просто функция, которую делегат эс в зависимости от случайного класса:

public static int rInt(int exclUB, int incLB = 0) 
    { 
     Random rand = new Random(DateTime.Now.Millisecond); 
     int t = rand.Next(incLB, exclUB); 
     rand = null;    
     return t; 
    } 

Но когда я называю generateTrainingInts, то же число помещён каждый раз. Однако, если я изменяю rInt на использование статического экземпляра класса Random, вместо локального экземпляра (с областью действия, как это определено выше), то он работает корректно (enqueue random integers). Кто-нибудь знает, почему это происходит?

Редактировать: Дорогой Ответчик, который не прочитал мой вопрос полностью, Как некоторые из вас указали, я ищу хорошее объяснение, почему это происходит. Я не ищу решение проблемы с тем же номером, потому что я уже исправил это, как я сказал выше. Спасибо за ваш энтузиазм, хотя :) Я просто хочу понять такие вещи, потому что моя первая реализация поняла мне концептуально.

+0

Кажется дублируют ... Посмотрите на realted вопросы, как -http: //stackoverflow.com/questions/1437825/random-number-generation-in-c –

+0

Это происходит потому, что объект 'Random' инициализируется из 'окружающей среды.GetTickCount', который является миллисекундным таймером. Поэтому, если вы дважды вызываете конструктор «Случайный» в течение одной миллисекунды, вы получите то же начальное значение. –

+0

Когда rand создается с тем же самым семенем (например, DateTime.Now.Millisecond в вашем случае), он возвращает те же последовательности значений. Вы должны создать экземпляр его один раз (и сохранить его в статической переменной) или с разными семенами каждый раз. – AFract

ответ

23

Вам необходимо сохранить тот же объект Random. Положите его вне вашего статический метод как статический член

private static Random rand = new Random(); 

public static int rInt(int exclUB, int incLB = 0) 
{ 
    int t = rand.Next(incLB, exclUB); 
    return t; 
} 

Редактировать
Причиной этого является конечное разрешение часов используется для инициализации Random. Последующие инициализации Random получат одну и ту же начальную позицию в случайной последовательности. При повторном использовании одного и того же Random всегда генерируется следующее значение в случайной последовательности.

+0

ОП уже пробовал это и спрашивал * почему *. –

+0

Зачем присваивать rand null после генерации ?? Поскольку rand будет создан в очень короткий промежуток времени, оба экземпляра получат одно и то же семя и возвратят одинаковое значение, точно так же, как в авторской версии. Вы должны ставить его статичным и всегда хранить один и тот же экземпляр. Также возможно использовать несколько экземпляров с разными семенами, например, используя «Guid.NewGuid(). GetHashCode()» в качестве семени, но вы получите ужасные результаты. – AFract

+0

Я вижу, что вы скорректировали свой образец кода. Это был boggus, но он должен теперь работать ... – AFract

5

Попробуйте следующий код, и я думаю, вы поймете, почему:

void PrintNowAHundredTimes() 
{ 
    for (int i = 0; i < 100; ++i) 
    { 
     Console.WriteLine(DateTime.Now); 
    } 
} 

В Random объектах получают то же семя снова и снова. Это связано с тем, что гранулярность системного времени, возвращаемая DateTime.Now, довольно проста. Например, на моей машине значение изменяется только каждые ~ 15 мс. Таким образом, последовательные вызовы в течение этого периода времени возвращаются в одно и то же время.

И как я подозреваю, вы уже знаете, два объекта Random, инициализированные с тем же начальным значением, будут генерировать идентичные случайные последовательности. (Вот почему это называется псевдослучайных технически.)

Вы также должны знать, что даже если это имеет смысл для создания экземпляра нового объекта Random локально в пределах вашего метода, установив его на null не будет по-прежнему служить никакой цели (когда метод выходит, в любом случае больше не будет ссылок на объект, поэтому он будет собирать мусор независимо).

1
public class JE_Rand 
{ 
    private static Random rand= new Random(DateTime.Now.Millisecond); 

    public static int rInt(int exclUB, int incLB = 0) 
    { 
     int t = rand.Next(incLB, exclUB); 
     return t; 
    } 
} 
+0

Почему rand = null? он будет сбрасывать объект, а следующий вызов будет вызывать исключение – walter

+0

@walter: Это старый ответ, но я просто копировал и вставлял его код и перемещал новый Random (....) вне вызова метода. Вы на 100% прав. Я отредактирую свой ответ. – BFree

Смежные вопросы