2012-01-18 266 views
1

为了澄清,多个学生对象和他们都获得相同的价值。随机不工作

我知道这个问题已经被问过,但我没有与其他职位有关他的话题的运气。我有一个从1到3的随机数字发生器。然后,我们使用%2来使布尔值为真或假。每次我运行程序时,我都会得到全部真实或全部假。这是我的代码。我知道随机并不是真正的随机。我能做些什么来获得更多的随机数字。

Random random = new Random(); 

public Student() 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
} 

public bool readingLevel()//this always returns one value for the entire program. 
{ 
    return level; 
} 
+0

你是怎么学习这门课的? – 2012-01-18 23:01:45

+0

你是否在循环中使用它? – 2012-01-18 23:01:51

+0

请提供一个完整的示例。 – 2012-01-18 23:03:06

回答

7

你只分配一个随机值“级别”的构造过程中一次,所以它总是有初始值。 尝试:

public bool readingLevel() 
{ 
    return (random.Next(1,3) % 2 == 0); 
} 

编辑:

Static Random random = new Random(); 
... 
+1

鉴于上下文,我假设(是的,假设)他有多个学生,他们都获得相同的价值。我相信他的意图是让学生有一个不变的“水平”。 – 2012-01-18 23:03:51

+0

我正试图让不同的值有多个学生。我一直认为每次创建新对象时都会调用构造函数。如果是这种情况,那么不应该每个对象都有不同的值吗? – Aaron 2012-01-18 23:30:52

+0

@Aaron在这种情况下,你应该为这个类使用一个静态的随机数字生成器,因为它表明每个学生正在使用相同的种子值创建导致你的问题。请参阅编辑 – 2012-01-18 23:37:04

-1
Random random = new Random(DateTime.Now.Ticks); 
+2

默认的构造函数已经按时间播种了。 – CodesInChaos 2012-01-18 23:04:45

+0

嗯,我想你每天都会学到新的东西:) – neeKo 2012-01-18 23:06:46

2
public Student() 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
} 

看起来非常像的Student类的构造函数。在这个构造函数中,你基本上是计算一个随机数并将其存储在level字段中。因此,如果在整个程序中使用相同的Student实例并在此实例上多次调用readingLevel()方法,它显然会返回相同的值 - >在构建此实例期间完成的那个值,并且您存储在level领域。

所以,你可能会考虑随机数生成逻辑移动到readingLevel()方法,而不是简单地在返回相同的数值一遍又一遍:

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

    public bool readingLevel() 
    { 
     int randomLevel = random.Next(1,3); 
     return (randomLevel % 2 == 0); 
    } 
} 

现在每次调用此方法在同一个情况下,你应该得到一个新的随机数的计算。

2

仅创建Random的一个实例并重新使用它。在快速连续种子中创建多个随机数的实例,以获得相同的值,从而产生相同的序列。

如果你的代码在单线程中,你可以简单地使用一个静态属性来保存Random的实例。

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

http://msdn.microsoft.com/en-us/library/h343ddh9.aspx

+0

虽然这显然是真的,但这不是他的问题的原因。 – 2012-01-18 23:03:29

+0

@NoonSilk为什么?除了这个问题,每个“学生”实例都会有自己的阅读水平。 – CodesInChaos 2012-01-18 23:05:16

+0

这可能是我误解了他的问题的规范。 – 2012-01-18 23:06:42

0

您正在使用的随机模拟真/假的情况,所以您要限制结果为1或2。鉴于您对结果做一个奇/​​偶测试,你可能会更好做:

int randomLevel = random.Next(); 
level = (randomLevel % 2 == 0); 

此外,如果你创建你所有的学生接二连三有一个很好的机会,你当前的代码将返回相同的值用于随后的通话。

0

好吧。

想想这里发生了什么。当您的Student构建时,您会得到一些随机数,然后将其设置为成员变量level

然后,在其他点上,您可以调用一个函数readingLevel,它返回此前设置的值。

然后,你可以思考一下自己:这个函数何时会给出不同的值?那么,只有当level获得不同的值时才会这样做。这是什么时候发生的?那么,它只发生在构造函数中,所以,这意味着,它永远不会再发生对象的生命......

+0

但我只希望每个对象具有一个readingLevel值。如果Level只在构造函数中获得一个新值,那么不会每次创建一个新对象时,构造函数都会被调用,并且一个新的readingLevel会得到一个新的数字。如果是这样,它正在做我想做的事情。但是,每个对象对于readineLevel都会得到相同的结果。我错过了什么 – Aaron 2012-01-18 23:26:16

0

这是因为您正在使用random.Next()和您的类的构造函数中的级别评估,请记住,只有在创建对象的新实例时才执行构造函数,因为它会执行多次创建一个不同的方法,您可以在其中调用随机和级别评估,这样您每次都可以获得不同的值或使用例如:

public bool Level() 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
    return level; 
} 
+0

'level'不能同时是一个字段和方法... – CodesInChaos 2012-01-18 23:13:48

+0

@CodeInChaos:但是,'level'和'Level'可以。在编辑之前,它读作“public bool reading level()”,由于阅读和关卡之间的拼写错误而导致语法无效,更不用说命名字段和方法是相同的。 – 2012-01-18 23:28:03

0

请尝试以下操作。将随机等级的选择移至readingLevel函数。

Random random = new Random(); 
public Student() 
{ 
} 

public bool readingLevel()//this always returns one value for the entire program. 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
    return level; 
} 
3

它看起来就像你正在试图获得一个随机数!
大眼夹

那么你可以尝试这样的事:

static Random random = new Random(); 

public Student() 
{ 
    lock (random) 
    { 
     int randomLevel=random.Next(1,3); 
     level = (randomLevel % 2 == 0); 
    } 
} 
public bool readingLevel()//this always returns one value for the entire program. 
{ 
    return level; 
} 

与片断的问题似乎是,你实例化一个新的Random类与每个类的实例。 这不是Random应该被使用的方式,而是应该使用Random类实例来获取多个随机数。

原因在于.Net中的随机数使用基于状态(种子)的伪随机算法,每当你要求一个新的随机数时该状态就会改变。通过在相对较短的时间范围内实例化多个随机类,所有这些类都将以相同的种子启动(基于系统时间),并且所有这些类都会给出相同的随机数。

+0

同时用于调用Clippy的+1和-1。 (+1,因为它很有趣; -1因为它是......好吧,Clippy) – 2012-01-18 23:09:19

3

它看起来像你的随机生成器是学生的实例变量。由于生成器使用当前时间作为种子,如果您在短时间内创建了一群学生,他们都将拥有一个具有相同种子和相同结果的生成器。你可以使随机生成器成为一个静态变量,或者更好的是,使用构造函数注入并将该关卡传递给Student的构造函数。

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

    public Student() 
    { 
    level = random.NextDouble() < 0.5; 
    } 

    public bool readingLevel() 
    { 
    return level; 
    } 
} 

或使用constructor injection所以你的学生班是确定性的。

class Student 
{ 
    private boolean level; 

    public Student(boolean readingLevel) 
    { 
    this.level = readingLevel; 
    } 
    public boolean readingLevel() 
    { 
    return level; 
    } 
} 
1

其他人也这么说过,但我认为这个观点值得用一个例子来强调。

public class Student 
{ 
    Random random = new Random(); 

    public Student() 
    { 
     int randomLevel=random.Next(1,3); 
     level = (randomLevel % 2 == 0); 
    } 

    public bool readingLevel()//this always returns one value for the entire program. 
    { 
     return level; 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     var students = new List<Student>(); 
     for (int i = 0; i < 10; i++) 
      students.Add(new Student()); 

     //Now you have 10 Students; each Student has its own random number generator 
     //The generators were created within microseconds of each other, so they most likely have THE SAME SEED 
     //Because they have the same seed, they will generate identical sequences of numbers 
     //Each student's reading level is calculated from the first call to .Next(1, 3) on its own RNG. 
     //The RNGs have the same seed, so each will return the same value for the first call to .Next(1, 3) 
     //Therefore, all students will have the same reading level! 
    } 
}