随机数发生器只生成一个随机数

我有以下function:

//Function to get random number public static int RandomNumber(int min, int max) { Random random = new Random(); return random.Next(min, max); } 

我怎么称呼它:

 byte[] mac = new byte[6]; for (int x = 0; x < 6; ++x) mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256); 

如果我在运行时使用debugging器执行该循环,则会得到不同的值(这是我想要的)。 但是,如果我在该代码下面放置了两行断点,则“mac”数组的所有成员都具有相同的值。

为什么会发生?

每当你做new Random()它是使用时钟初始化。 这意味着,在一个紧密的循环中,您可以获得相同的价值。 你应该保持一个Random实例,并在同一个实例上继续使用Next

 //Function to get a random number private static readonly Random random = new Random(); private static readonly object syncLock = new object(); public static int RandomNumber(int min, int max) { lock(syncLock) { // synchronize return random.Next(min, max); } } 

编辑(见评论):为什么我们需要在这里lock

基本上, Next将改变Random实例的内部状态。 如果我们同时从多个线程做到这一点,那么你可能会说“我们刚刚把结果变得更加随机”,但是我们实际上正在做的是有可能打破内部实现,并且我们也可能开始得到相同的数字从不同的线程,这可能是一个问题 – 可能不会。 尽pipe如此,保证内部发生的是更大的问题。 因为Random没有保证线程安全。 因此有两种有效的方法:

  • 同步,以便我们不会同时从不同的线程访问它
  • 每个线程使用不同的Random实例

要么可以罚款; 但是同时从多个呼叫者中分离一个单一实例只是要求麻烦。

lock实现了这些方法的第一个(也是简单的) 然而,另一种方法可能是:

 private static readonly ThreadLocal<Random> appRandom = new ThreadLocal<Random>(() => new Random()); 

这是每个线程,所以你不需要同步。

为了便于在整个应用程序中重用,静态类可能会有所帮助。

 public static class StaticRandom { private static int seed; private static ThreadLocal<Random> threadLocal = new ThreadLocal<Random> (() => new Random(Interlocked.Increment(ref seed))); static StaticRandom() { seed = Environment.TickCount; } public static Random Instance { get { return threadLocal.Value; } } } 

您可以使用静态随机实例,如代码

 StaticRandom.Instance.Next(1, 100); 

Mark的解决scheme可能相当昂贵,因为它需要每次同步。

我们可以通过使用线程特定的存储模式来解决同步的需求:

 public class RandomNumber : IRandomNumber { private static readonly Random Global = new Random(); [ThreadStatic] private static Random _local; public int Next(int max) { var localBuffer = _local; if (localBuffer == null) { int seed; lock(Global) seed = Global.Next(); localBuffer = new Random(seed); _local = localBuffer; } return localBuffer.Next(max); } } 

衡量这两个实现,你应该看到显着的差异。

我从这里回答:

只是重申正确的解决scheme

 namespace mySpace { public static class Util { private static rnd = new Random(); public static int GetRandom() { return rnd.Next(); } } } 

所以你可以打电话给:

 var i = Util.GetRandom(); 

全部。

如果你严格需要一个真正的无状态静态方法来产生随机数,你可以依靠一个Guid

 public static class Util { public static int GetRandom() { return Guid.NewGuid().GetHashCode(); } } 

至less从我的经验来看, 这会稍慢一点,但可以Random.Next 更随机

不是

 new Random(Guid.NewGuid().GetHashCode()).Next(); 

不必要的对象创build会让它慢下来,特别是在循环下。

永远不要

 new Random().Next(); 

不仅它慢(在一个循环内),它的随机性是…根据我的说法,并不是很好。

我宁愿使用下面的类来生成随机数字:

 byte[] random; System.Security.Cryptography.RNGCryptoServiceProvider prov = new System.Security.Cryptography.RNGCryptoServiceProvider(); prov.GetBytes(random); 

1)正如Marc Gravell所说,尝试使用一个随机发生器。 将它添加到构造函数中总是很酷:System.Environment.TickCount。

2)一个小费。 假设你想创build100个对象,并假设每个对象都应该有自己的随机生成器(如果在很短的时间内计算随机数的LOADS)。 如果你要做一个循环(产生100个对象),你可以这样做(为了保证完全的随机性):

 int inMyRandSeed; for(int i=0;i<100;i++) { inMyRandSeed = System.Environment.TickCount + i; . . . myNewObject = new MyNewObject(inMyRandSeed); . . . } // Usage: Random m_rndGen = new Random(inMyRandSeed); 

干杯。

这里有很多解决方法,这里是一个:如果你只想删除数字,方法会收到一个随机的结果长度。

 public String GenerateRandom(Random oRandom, int iLongitudPin) { String sCharacters = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ123456789"; int iLength = sCharacters.Length; char cCharacter; int iLongitudNuevaCadena = iLongitudPin; String sRandomResult = ""; for (int i = 0; i < iLongitudNuevaCadena; i++) { cCharacter = sCharacters[oRandom.Next(iLength)]; sRandomResult += cCharacter.ToString(); } return (sRandomResult); } 

如果你想使用一个函数来创build一个Random的实例,每次你可以使用这个:

 Threading.Thread.Sleep(1) Dim random As New Random(System.DateTime.Now.Millisecond) Dim secret = random.Next(10000, 100000) 

这将产生随机数字。 根据需要调整它。

 private static void Main(string[] args) { var randoms = GetRandomNumbers(1, 1000, 50); } private static IEnumerable<int> GetRandomNumbers(int low, int high, int numberOfRandoms) { Random rnd = new Random(); var unique = new HashSet<int>(); do { int num = rnd.Next(low, high); if (unique.Contains(num)) continue; unique.Add(num); } while (unique.Count < numberOfRandoms); return unique.ToList(); } 

(== Try Me ==)