Ласкаво просимо до dev.net.ua Увійти | Приєднатися | Допомога | Увійти Live ID

Denis Reznik's blog

Блог о SQL Server и технологиях Microsoft

Насколько случайным бывает Random

        Недавно один из членов моей комманды задал мне вопрос: "Почему генерация случайных чисел в .Net упорно выдаёт не рэндомные значения, а повторяющиеся?". И последовательный вызов вот такого метода, всегда генерирует одну и ту же последовательность чисел:
 
   1: const string AllowableCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
   2:         
   3: public static string GenerateRandomString(int length)
   4: {
   5:     string randomString = String.Empty;
   6:     Random random = new Random();
   7:     for (int i = 0; i < length; i++)
   8:         randomString += AllowableCharacters[random.Next(AllowableCharacters.Length)];
   9:  
  10:     return randomString;
  11: }
 
        Случай меня заинтересовал, и я полез в рефлектор чтобы понять причину такого поведения. Вот, что я там увидел:
 
   1: public Random() : this(Environment.TickCount) {}
 
        Наверное ни для кого не секрет, что генерация случайных чисел в .Net (и не только в .Net) базируется на использовании некоего начального значения, которое должно быть уникальным. Для получений таких значений часто используется уникальная, в данном контексте, метка времени. Как видно из кода, конструктор по умолчанию, в качестве такого, значения использует Environment.TickCount  - время, прошедшее со старта приложения, в миллисекундах. Т.е. получается, что если ваши объекты Random создаются с интервалом меньше миллиcекунды, при помощи конструктора по умолчанию – они будут инициализированы одним и тем же параметром, что в свою очередь влечёт генерацию одинаковых последовательностей "случайных" чисел.

        На форумах можно встретить несколько вариантов решения проблемы, таких как передачу в конструктор более мелкого промежутка времени (например DateTime.Now.Ticks), задержка между вызовами методов при помощи Thread.Sleep. Но исходя из всего вышесказанного, наилучшим варантом, гарантирующим генерацию случайных чисел, является использование одного экземпляра класса Random:

   1: public static string GenerateRealRandomString(int length, Random random)
   2: {
   3:     string randomString = String.Empty;
   4:     for (int i = 0; i < length; i++)
   5:         randomString += AllowableCharacters[random.Next(AllowableCharacters.Length)];
   6:  
   7:     return randomString;
 
        Где вызов метода, осуществляется таким образом:
 
   1: Random random = new Random();
   2: Console.WriteLine(GenerateRealRandomString(10, random));
   3: Console.WriteLine(GenerateRealRandomString(10, random));

 

Материалы поста:

- Насколько случайным бывает Random

Ссылки по теме:

photo of Denis ReznikDenis Reznik
LPP Soft, .Net Team Lead
Kharkov, Ukraine
Опубліковані 23-01-2010 03:52 від Denis Reznik
Зареєстрований як , , ,

Коментарі

 

ryltsov said:

Кстати, все то же самое написано и в документации на класс Random. Помимо этого там отмечено как получить гораздо более надежно случайную последовтельность используя Crypto API.

January 24, 2010 7:28 AM
 

progg.ru said:

Thank you for submitting this cool story - Trackback from progg.ru

January 28, 2010 12:55 AM
Анонімні коментарі деактивовані. Увійдіть або Зареєструйтесь щоб мати доступ до ресурсів Спільноти.

Новини

twitter

Календар повідомлень

<January 2010>
SMTWTFS
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

Пошук

Go

Категорії повідомлень

Синдикація

SkinName:iroha_Blog2