Multiple random numbers are the same
Possible Duplicate:
Random number generator only generating one random number
初学者的问题。我有一个非常简单的程序,它画了一条线,我想随机化位置,但是每次我创建一个新的随机实例,它都会返回相同的值。问题出在哪里?谢谢您。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | private void Draw() { Random random1 = new Random(); int randomNumber1 = random1.Next(0, 300); Random random2 = new Random(); int randomNumber2 = random2.Next(0, 300); Random random3 = new Random(); int randomNumber3 = random3.Next(0, 300); Random random4 = new Random(); int randomNumber4 = random4.Next(0, 300); System.Drawing.Graphics g = this.CreateGraphics(); Pen green = new Pen(Color.Green, 5); g.DrawLine(green, new Point(randomNumber1, randomNumber2), new Point(randomNumber3, randomNumber4)); } private void btndraw1_Click(object sender, EventArgs e) { Draw(); } |
发生这种情况的原因是,每次执行新的
要解决这个问题:只创建一个随机变量,最好是在函数外部,并且只使用那个实例。
1 2 3 4 5 6 7 8 9 10 11 | Random random1 = new Random(); private void Draw() { int randomNumber1 = random1.Next(0, 300); int randomNumber2 = random1.Next(0, 300); int randomNumber3 = random1.Next(0, 300); int randomNumber4 = random1.Next(0, 300); System.Drawing.Graphics g = this.CreateGraphics(); Pen green = new Pen(Color.Green, 5); g.DrawLine(green, new Point(randomNumber1, randomNumber2), new Point(randomNumber3, randomNumber4)); } |
只需使用相同的实例:
1 2 3 4 | Random random = new Random(); int randomNumber1 = random.Next(0, 300); int randomNumber2 = random.Next(0, 300); //... |
编程中的随机数并不是真正的随机数;它们是基于一些独特的种子,这些种子被获取和操作以生成看起来是一组随机数的东西。使用相同的种子将产生相同的数字集。
实际上没有理由创建不止一次的
为了证明我的上述默认种子声明,我使用了反射:
1 2 3 4 5 | // System.Random /// <summary>Initializes a new instance of the <see cref="T:System.Random" /> class, using a time-dependent default seed value.</summary> public Random() : this(Environment.TickCount) { } |
以及
1 2 3 4 5 6 7 8 9 10 | // System.Environment /// <summary>Gets the number of milliseconds elapsed since the system started.</summary> /// <returns>A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.</returns> /// <filterpriority>1</filterpriority> public static extern int TickCount { [SecuritySafeCritical] [MethodImpl(MethodImplOptions.InternalCall)] get; } |
随机数生成器(RNG)实际上并不生成随机数。相反,它使用一种算法来定义一个随机的数字序列。此序列取决于创建RNG时通过所述算法运行的
默认情况下,RNG是使用系统的时钟作为种子创建的,因为时钟通常在程序每次运行时都会变化,这使得预测"随机"序列非常困难。
在您的例子中,很可能时钟在创建一个随机对象和另一个随机对象之间没有变化;可能是由于CPU内部对指令的重新排序。
正如blachshma所说,最好只创建一个随机对象并只使用它。
1 2 3 4 5 6 7 | public static Random MyRNG = new Random(); // create a single static random object, that you can use across all classes private void Draw() { randomNumber1 = MyRNG.Next(0, 300); randomNumber2 = MyRNG.Next(0, 300); // and so forth } |
请记住,
1 2 3 4 | lock (MyRNG) { randomNumber = MyRNG.Next(0, 300); } |
如果不这样做,可能会破坏随机对象,从而导致后续调用仅返回0。
您不应该为每个数字创建一个新的
1 2 3 4 5 6 7 8 9 10 11 12 | Random r = new Random(); private void Draw() { // Create 4 random numbers int[] numbers = Enumerable.Range(0, 4).Select(x => r.Next(0, 300)).ToArray(); System.Drawing.Graphics g = this.CreateGraphics(); Pen green = new Pen(Color.Green, 5); g.DrawLine(green, new Point(numbers[0], numbers[1]), new Point(numbers[2], numbers[3])); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private static readonly Random Random1 = new Random(); private void Draw() { int randomNumber1 = Random1.Next(0, 300); int randomNumber2 = Random1.Next(0, 300); int randomNumber3 = Random1.Next(0, 300); int randomNumber4 = Random1.Next(0, 300); System.Drawing.Graphics g = this.CreateGraphics(); Pen green = new Pen(Color.Green, 5); g.DrawLine(green, new Point(randomNumber1, randomNumber2), new Point(randomNumber3, randomNumber4)); } private void btndraw1_Click(object sender, EventArgs e) { Draw(); } |
您只需要随机类的一个实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | private void Draw() { Random random1 = new Random(); int randomNumber1 = random1.Next(0, 300); int randomNumber2 = random1.Next(0, 300); int randomNumber3 = random1.Next(0, 300); int randomNumber4 = random1.Next(0, 300); System.Drawing.Graphics g = this.CreateGraphics(); Pen green = new Pen(Color.Green, 5); g.DrawLine(green, new Point(randomNumber1, randomNumber2), new Point(randomNumber3, randomNumber4)); } private void btndraw1_Click(object sender, EventArgs e) { Draw(); } |
.NET的随机类需要的是一个种子值,您可以使用一个日期值作为种子,它将起作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | private void Draw() { Random random1 = new Random(unchecked((int)DateTime.Now.Ticks << (int)100)); int randomNumber1 = random1.Next(0, 300); Random random2 = new Random(unchecked((int)DateTime.Now.Ticks << (int)200)); int randomNumber2 = random2.Next(0, 300); Random random3 = new Random(unchecked((int)DateTime.Now.Ticks << (int)300)); int randomNumber3 = random3.Next(0, 300); Random random4 = new Random(unchecked((int)DateTime.Now.Ticks << (int)400)); int randomNumber4 = random4.Next(0, 300); System.Drawing.Graphics g = this.CreateGraphics(); Pen green = new Pen(Color.Green, 5); g.DrawLine(green, new Point(randomNumber1, randomNumber2), new Point(randomNumber3, randomNumber4)); } private void btndraw1_Click(object sender, EventArgs e) { Draw(); } |