随机数发生器只生成一个随机数
我有以下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 ==)