C# 随机数生成器只生成一个随机数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/767999/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Random number generator only generating one random number
提问by Ivan Prodanov
I have the following function:
我有以下功能:
//Function to get random number
public static int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
How I call it:
我怎么称呼它:
byte[] mac = new byte[6];
for (int x = 0; x < 6; ++x)
mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);
If I step that loop with the debugger during runtime I get different values (which is what I want).
However, if I put a breakpoint two lines below that code, all members of the macarray have equal value.
如果我在运行时使用调试器执行该循环,我会得到不同的值(这是我想要的)。但是,如果我在该代码下方两行放置一个断点,则mac数组的所有成员都具有相同的值。
Why does that happen?
为什么会这样?
采纳答案by Marc Gravell
Every time you do new Random()it is initialized using the clock. This means that in a tight loop you get the same value lots of times. You should keep a single Randominstance and keep using Nexton the sameinstance.
每次执行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);
}
}
Edit (see comments): why do we need a lockhere?
编辑(见评论):为什么我们需要lock这里?
Basically, Nextis going to change the internal state of the Randominstance. If we do that at the same time from multiple threads, you couldargue "we've just made the outcome even more random", but what we are actuallydoing is potentially breaking the internal implementation, and we could also start getting the same numbers from different threads, which mightbe a problem - and might not. The guarantee of what happens internally is the bigger issue, though; since Randomdoes notmake any guarantees of thread-safety. Thus there are two valid approaches:
基本上,Next将改变Random实例的内部状态。如果我们从多个线程同时执行此操作,您可能会争辩说“我们只是使结果更加随机”,但我们实际所做的可能会破坏内部实现,并且我们也可以开始获得相同的数字来自不同的线程,这可能是一个问题 - 也可能不是。但是,对内部发生的事情的保证是更大的问题。因为Random它不是让线程安全的任何保证。因此,有两种有效的方法:
- Synchronize so that we don't access it at the same time from different threads
- Use different
Randominstances per thread
- 同步,这样我们就不会从不同的线程同时访问它
Random每个线程使用不同的实例
Either can be fine; but mutexing a singleinstance from multiple callers at the same time is just asking for trouble.
两者都可以;但是同时互斥来自多个调用者的单个实例只是自找麻烦。
The lockachieves the first (and simpler) of these approaches; however, another approach might be:
在lock实现这些方法的第一(和更简单); 然而,另一种方法可能是:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
this is then per-thread, so you don't need to synchronize.
这是每个线程的,所以你不需要同步。
回答by fARcRY
I would rather use the following class to generate random numbers:
我宁愿使用以下类来生成随机数:
byte[] random;
System.Security.Cryptography.RNGCryptoServiceProvider prov = new System.Security.Cryptography.RNGCryptoServiceProvider();
prov.GetBytes(random);
回答by sabiland
1) As Marc Gravell said, try to use ONE random-generator. It's always cool to add this to the constructor: System.Environment.TickCount.
1) 正如 Marc Gravell 所说,尝试使用 ONE 随机生成器。将它添加到构造函数中总是很酷的:System.Environment.TickCount。
2) One tip. Let's say you want to create 100 objects and suppose each of them should have its-own random-generator (handy if you calculate LOADS of random numbers in a very short period of time). If you would do this in a loop (generation of 100 objects), you could do this like that (to assure fully-randomness):
2)一个提示。假设您想创建 100 个对象,并假设每个对象都应该有自己的随机生成器(如果您在很短的时间内计算随机数的负载,则很方便)。如果您要在循环中执行此操作(生成 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);
Cheers.
干杯。
回答by Hans Malherbe
Mark's solution can be quite expensive since it needs to synchronize everytime.
Mark 的解决方案可能非常昂贵,因为它每次都需要同步。
We can get around the need for synchronization by using the thread-specific storage pattern:
我们可以通过使用特定于线程的存储模式来解决同步的需要:
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);
}
}
Measure the two implementations and you should see a significant difference.
测量这两个实现,您应该会看到显着差异。
回答by Phil
For ease of re-use throughout your application a static class may help.
为了便于在整个应用程序中重用,静态类可能会有所帮助。
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; } }
}
You can use then use static random instance with code such as
您可以将静态随机实例与代码一起使用,例如
StaticRandom.Instance.Next(1, 100);
回答by nawfal
My answer from here:
我的回答来自这里:
Just reiterating the right solution:
只是重申正确的解决方案:
namespace mySpace
{
public static class Util
{
private static rnd = new Random();
public static int GetRandom()
{
return rnd.Next();
}
}
}
So you can call:
所以你可以调用:
var i = Util.GetRandom();
all throughout.
整个过程。
If you strictly need a true stateless static methodto generate random numbers, you can rely on a Guid.
如果您严格需要一个真正的无状态静态方法来生成随机数,则可以依靠Guid.
public static class Util
{
public static int GetRandom()
{
return Guid.NewGuid().GetHashCode();
}
}
It's going to be a wee bit slower, but can be much more randomthan Random.Next, at least from my experience.
它会慢一点,但可能比 随机得多Random.Next,至少从我的经验来看。
But not:
但不是:
new Random(Guid.NewGuid().GetHashCode()).Next();
The unnecessary object creation is going to make it slower especially under a loop.
不必要的对象创建会使其变慢,尤其是在循环下。
And never:
并且永远不会:
new Random().Next();
Not only it's slower (inside a loop), its randomness is... well not really good according to me..
它不仅更慢(在循环内),而且它的随机性......据我说并不是很好......
回答by Marztres
There are a lot of solutions, here one: if you want only number erase the letters and the method receives a random and the result length.
有很多解决方案,这里有一个:如果你只想数字擦除字母并且该方法接收随机和结果长度。
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);
}
回答by Abdul
just declare the Random class variable like this:
只需像这样声明 Random 类变量:
Random r = new Random();
// ... Get three random numbers.
// Here you'll get numbers from 5 to 9
Console.WriteLine(r.Next(5, 10));
if you want to get different random number each time from your list then use
如果您想每次从列表中获得不同的随机数,请使用
r.Next(StartPoint,EndPoint) //Here end point will not be included
Each time by declaring Random r = new Random()once.
每次通过声明Random r = new Random()一次。
回答by Joma
Every time you execute
每次执行
Random random = new Random (15);
It does not matter if you execute it millions of times, you will always use the same seed.
执行数百万次都没有关系,您将始终使用相同的种子。
If you use
如果你使用
Random random = new Random ();
You get different random number sequence, if a hacker guesses the seed and your algorithm is related to the security of your system - your algorithm is broken. I you execute mult. In this constructor the seed is specified by the system clock and if several instances are created in a very short period of time (milliseconds) it is possible that they may have the same seed.
您会得到不同的随机数序列,如果黑客猜到了种子并且您的算法与系统的安全性有关 - 您的算法已损坏。我你执行多。在这个构造函数中,种子由系统时钟指定,如果在很短的时间(毫秒)内创建了多个实例,它们可能具有相同的种子。
If you need safe random numbers you must use the class
如果您需要安全的随机数,则必须使用该类
System.Security.Cryptography.RNGCryptoServiceProvider
System.Security.Cryptography.RNGCryptoServiceProvider
public static int Next(int min, int max)
{
if(min >= max)
{
throw new ArgumentException("Min value is greater or equals than Max value.");
}
byte[] intBytes = new byte[4];
using(RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
rng.GetNonZeroBytes(intBytes);
}
return min + Math.Abs(BitConverter.ToInt32(intBytes, 0)) % (max - min + 1);
}
Usage:
用法:
int randomNumber = Next(1,100);

