5

我需要创建一组独特的线条来测试我正在从事的不同项目。

所以我创建了一个简单的程序来生成一个 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() 总是会返回一个新的随机数?

4

6 回答 6

25

您创建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,这样它就不必在循环期间重新分配。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();        
}
于 2009-04-30T16:44:31.890 回答
12

请参阅MSN 上的随机构造函数描述,这部分:

默认种子值来自系统时钟并且具有有限的分辨率。因此,通过调用默认构造函数连续创建的不同 Random 对象将具有相同的默认种子值,因此将产生相同的随机数集。

因此,要么在程序开始时只调用一次 Random() 构造函数,要么使用 Random(int32) 构造函数并自己定义一个可变种子。

于 2009-04-30T16:44:48.693 回答
4

因为您在每次调用中都会创建一个新的 Random 对象。

只需将 randomNumber 从方法中移出并使其成为类成员。

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

所有软件随机生成器都是“伪随机”,它们基于(起始)种子生成一系列数字。使用相同的种子,它们会产生相同的序列。有时这很有用。如果要生成程序以在每次运行时生成相同的序列,可以使用new Random(0).

编辑:显然.Net Random 类是自动播种的,我不知道。因此,正如其他人指出的那样,这是一个时间问题。

于 2009-04-30T16:43:00.820 回答
3

类似的问题,很多答案:

随机字符串生成 - 两个一个接一个产生相同的结果

于 2009-04-30T16:45:35.163 回答
3

只声明一次 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();        
    }
}
于 2009-04-30T16:49:44.780 回答
1

由于花费的时间很短,随机数的种子都是相同的,实际上您每次都使用相同的种子重新创建随机生成器,因此 Next() 调用返回相同的随机值。

于 2009-04-30T16:46:05.070 回答