首页 文章

每次调用构造函数时,如何更改C#随机数生成器?

提问于
浏览
2

我有两个班,一个教师班和一个 class 班 . 在我的程序中,我创建了一个包含10个Teacher对象的数组,每个Teacher对象中有一个包含10个Student对象的数组 . 每个Student对象还有一个整数数组作为成员变量,当每个Student被实例化时,它自己的整数数组中都填充了随机数生成器中的数字 . 我的程序是这样的:

  • 创建一个类型为Teacher的数组,大小为10

  • 然后用10个实际的教师对象填充数组

  • 每个Teacher对象包含一个大小为10的Student对象数组作为成员变量

  • 每个Teacher对象中的Student数组都填充了实际的Student对象

  • 每个学生对象都有一个整数数组,在学生对象构造函数中填充了随机数 .

这是我遇到的问题:似乎每次为每个教师创建10个Student对象时,即使我调用.Next()函数直到下一个,Student对象构造函数中的随机数生成器也不会重置或更改为下一个Teacher对象创建10个Student对象 . 我想要的是10个教师对象,每个对象都有自己的学生对象,这些对象有自己的整数数组,里面填充了随机生成的数字 .

任何帮助,将不胜感激!在我的最后一个问题中,我遇到了构造函数的这类问题,而这是一个问题是否是静态的,我不确定这次是什么情况 . 如果我对任何事情都不够清楚,请问我问题!

更新**所以在查看MSDN之后,我在他们的示例代码中找到了“Thread.Sleep(2000)”并将其粘贴到我的学生构造函数中,只是为了看看它做了什么 . 它似乎已经解决了问题,虽然我的程序现在运行速度慢很多,是否有一个最小的睡眠值要等到Random.Next()使用来自时钟的新种子,即使我确实解决了问题,是否有更好的方法吗?我的随机数生成器已经是Student的静态成员变量 .

3 回答

  • 1

    随机数生成器使用系统时间作为种子 . 我想知道你是否可能在系统有时间进入下一个增量之前声明一个新的发生器并调用它 . 处理器周期实际上通常比系统时钟更快 . 你能发一个代码示例吗?

    我建议将静态生成器声明为类属性或其他可访问的属性,将其实例化为final . 这将保证您不会用另一个覆盖发电机 .

  • 5

    如果在短时间内使用默认构造函数 Random() 初始化多个 Random 实例,则可能会导致它们最终具有相同的种子值(这取决于时间),因此每次都会生成相同的随机序列 .

    您可以通过初始化单个静态 Random 实例来解决此问题,并在所有 Student 实例之间共享它 . 只要您不是多线程,这是绝对安全的 .

    public class Student
    {
        private static readonly Random random = new Random();        
    }
    

    Random()构造函数的MSDN页面:

    默认种子值源自系统时钟并具有有限的分辨率 . 因此,通过调用默认构造函数紧密连续创建的不同Random对象将具有相同的默认种子值,因此将生成相同的随机数集 . 通过使用单个Random对象生成所有随机数可以避免此问题 . 您还可以通过修改系统时钟返回的种子值,然后将此新种子值显式提供给Random(Int32)构造函数来解决此问题 . 有关更多信息,请参阅Random(Int32)构造函数 .

    Edit :虽然您声明您的随机数生成器已经是静态成员,但如果您在每次 Student 初始化期间重复(冗余地)实例化它,这仍然是不够的 . 以下代码仍为 incorrect

    public class Student
    {
        private static Random random;
    
        private int[] numbers;
    
        public Student()
        {
            random = new Random();
            numbers = new int[10];
            for (int i = 0; i < 10; ++i)
                numbers[i] = random.Next();
        }
    }
    

    您需要将其替换为仅实例化 Random 一次的版本,如下所示:

    public class Student
    {
        private static readonly Random random = new Random();
    
        private int[] numbers;
    
        public Student()
        {
            numbers = new int[10];
            for (int i = 0; i < 10; ++i)
                numbers[i] = random.Next();
        }
    }
    
  • 5

    Random 的常见缺陷是每次需要随机值时创建一个新实例 .

    for (int i = 0; i < 1000; i++) {
       var random = new Random();
       list.Add(random.Next());
    }
    

    这不能按预期工作,因为 Random 使用实际时间来创建第一个随机值 . 但是,时钟的分辨率有限 . 可能是几个连续的迭代返回相同的时间,因此返回相同的(伪)随机值!

    解决方案是只创建一次 random .

    var random = new Random();
    for (int i = 0; i < 1000; i++) {
       list.Add(random.Next());
    }
    

    您还可以将 random 声明为静态类成员

    public static readonly Random RandomGenerator = new Random();
    

相关问题