почему этот метод возвращает одну и ту же случайную строку каждый раз? - PullRequest
5 голосов
/ 30 апреля 2009

Мне нужно создать блок уникальных строк, чтобы протестировать другой проект, над которым я работаю.

Итак, я создал простую программу для генерации случайной строки длиной X.

Проблема в том, что если я вызову его один раз, я получу случайную строку, если я вызову ее снова (например, в цикле for), я получу ту же строку для всего выполнения цикла.

У меня такое ощущение, что он кэшируется или что-то в этом роде, но я не знал, что .net сделал это, и я просто запутался в этом моменте.

телефонный код:

    StreamWriter SW = new StreamWriter("c:\\test.txt");
    int x = 100;
    while (x >0)
    {
        SW.WriteLine(RandomString(20));
        x--;
    }

вот метод:

private static string RandomString(int Length)
{
    StringBuilder sb = new StringBuilder();
    Random randomNumber = new Random();

    for (int i = 0; i <= Length; ++i)
    {
        int x = randomNumber.Next(65, 122);
        sb.Append(Convert.ToChar(x));
    }
    return sb.ToString();        
}

и вот вывод:

"VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
..................
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB"

Так что я думал, что Random.next () всегда будет возвращать новое случайное число?

Ответы [ 6 ]

25 голосов
/ 30 апреля 2009

Вы создаете экземпляры Random слишком близко по времени. Каждый экземпляр инициализируется с использованием системных часов, и поскольку часы не изменились, вы получаете одну и ту же последовательность случайных чисел снова и снова.

Создайте один экземпляр класса Random и используйте его снова и снова.

Используйте ключевое слово using, чтобы StreamWriter закрывался и удалялся, когда вы закончили с ним. Код для цикла легче распознать, если использовать ключевое слово for.

using (StreamWriter SW = new StreamWriter("c:\\test.txt")) {
   Random rnd = new Random();
   for (int x = 100; x > 0; x--) {
      SW.WriteLine(RandomString(rnd, 20));
   }
}

Метод принимает в качестве параметра объект Random.

Кроме того, используйте длину, чтобы инициализировать StringBuilder с правильной емкостью, чтобы он не перераспределялся во время цикла. Используйте оператор <вместо <= в цикле, иначе вы создадите строку, которая на один символ длиннее, чем указывает параметр <code>length.

private static string RandomString(Random rnd, int length) {
   StringBuilder sb = new StringBuilder(length);
   for (int i = 0; i < length; i++) {
      int x = rnd.Next(65, 122);
      sb.Append((char)x);
   }
   return sb.ToString();        
}
12 голосов
/ 30 апреля 2009

См. Случайное описание конструктора в MSN, эта часть:

Значение семени по умолчанию получено из системные часы и имеют конечное разрешающая способность. В результате разные Случайные объекты, созданные в близкая преемственность путем вызова к конструктор по умолчанию будет иметь идентичные начальные значения по умолчанию и, следовательно, будет производить идентичные наборы случайных чисел.

Так что либо вызовите конструктор Random () только один раз в начале вашей программы, либо используйте конструктор Random (int32) и определите переменное начальное число самостоятельно.

4 голосов
/ 30 апреля 2009

Поскольку вы создаете новый объект Random в каждом вызове.

Просто переместите randomNumber из метода и сделайте его членом класса.

private Random randomNumber = new Random();
private static string RandomString(int Length)
{
    StringBuilder sb = new StringBuilder();
    //...
}

Все программные генераторы случайных чисел являются «псевдослучайными», они производят последовательность оснований чисел на (начальном) семени С одним и тем же семенем они производят одинаковую последовательность. Иногда это полезно. Если вы хотите, чтобы ваша программа производила одну и ту же последовательность при каждом запуске, вы можете использовать new Random(0).

Редактировать: очевидно, что .Net Random класс - это автозаполнение, я этого не знал. Так что это проблема времени, как уже отмечали другие.

3 голосов
/ 30 апреля 2009

объявлять randomNumber только один раз



public class MyClass
{
    private static Random randomNumber = new Random();

    private static string RandomString(int Length)
    {
        StringBuilder sb = new StringBuilder();  

        for (int i = 0; i ... Length; ++i)
        {
        int x = MyClass.randomNumber.Next(65, 122);
        sb.Append(Convert.ToChar(x));
        }
        return sb.ToString();        
    }
}
3 голосов
/ 30 апреля 2009
1 голос
/ 30 апреля 2009

начальное число для случайных чисел одинаково из-за небольшого количества времени, которое требуется, фактически вы каждый раз воссоздаете генератор случайных чисел с одним и тем же начальным числом, поэтому вызов Next () возвращает одно и то же случайное значение.

...