【问题标题】:why does this method return the same random string each time?为什么这个方法每次都返回相同的随机字符串?
【发布时间】:2009-04-30 16:40:28
【问题描述】:

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

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

【问题讨论】:

标签: c# .net text random char


【解决方案1】:

您创建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();        
}

【讨论】:

    【解决方案2】:

    请参阅 MSN 上的Random constructor description,这部分:

    默认种子值来源于 系统时钟和有限 解析度。结果,不同 随机创建的对象 通过调用 默认构造函数将具有 相同的默认种子值,并且, 因此,将产生相同的集合 随机数。

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

    【讨论】:

      【解决方案3】:

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

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

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

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

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

      【讨论】:

      • .NET 的 Random 不是自动播种吗?
      • 而且...构造函数使用当前时间戳作为种子,因此每个项目都使用相同的种子,因此随机得出完全相同的答案... :)
      • 确实如此,但与时间相关的种子似乎不会经常改变,请参阅我的答案。
      • 问题不是自动播种。自动播种很好,但是连续创建多个 Random 对象意味着它们都具有相同的初始种子。
      • @mmyers。确实如此,根据系统时间,请参阅@schnaader 的答案。
      【解决方案4】:

      只声明 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();        
          }
      }
      

      【讨论】:

        【解决方案5】:

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-09
            • 2012-02-16
            • 2019-01-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多