如果我想创建一个 1 到 100 之间的随机数,为什么需要创建 Random 类的实例?
Random rand = new Random();
rand.Next(1,100);
Random类中是否有任何静态函数可以做同样的事情?如...
Random.Next(1,100);
我不想不必要地创建一个实例。如果我想创建一个 1 到 100 之间的随机数,为什么需要创建 Random 类的实例?
Random rand = new Random();
rand.Next(1,100);
Random类中是否有任何静态函数可以做同样的事情?如...
Random.Next(1,100);
我不想不必要地创建一个实例。最佳实践是创建单个Random
实例并在整个程序中使用它,否则结果可能不太随机。通过不创建静态函数来鼓励这种行为。
您不必担心“不必要地创建实例”,最好情况下影响可以忽略不计 - 这是框架的工作方式。
//Function to get 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);
}
}
这并不是“不必要的”,因为Random类在内部存储了一些状态。它这样做是为了确保如果您在非常短的时间内(在同一毫秒或滴答声等)多次调用.Next(),您仍然不会得到相同的数字。
当然,如果在您的情况下这不是问题,您可以将这两行代码合并成一行:
new Random().Next(1, 100);
你已经在这里得到了答案。再重申一下正确的解决方案:
namespace mySpace
{
public static class Util
{
private static Random 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();
}
}
虽然可能会稍微慢一些,但是根据我的经验,它比Random.Next
更加随机。
但是不是:
new Random(Guid.NewGuid().GetHashCode()).Next();
不必要的对象创建会使代码变慢,特别是在循环中。
而且绝不能:
new Random().Next();
在循环内使用它不仅会变慢,而且我认为它的随机性也不是很好。
new Random
... - usr.Next()
不是线程安全的,在并发使用下可能会抛出 IndexOutOfRange 异常。 - Lilith RiverThreadStatic
Random
实例:[ThreadStatic] static Random random;
Random Get() {
if (random == null) random = new Random(Guid.NewGuid().GetHashCode());
return random;
}
这个可以照顾到所有事情。
我不明白为什么.NET Framework(以及地球上的任何其他框架)不使用类似的东西。
“随机数生成从种子值开始。如果重复使用相同的种子,则生成相同的数字序列。产生不同序列的一种方法是使种子值依赖于时间,从而在每个新的 Random 实例中产生不同的序列。 默认情况下,Random 类的无参数构造函数使用系统时钟生成其种子值,而其参数化构造函数可以使用当前时间中的滴答数基于一个 Int32 值来生成种子值。 然而,由于时钟具有有限的分辨率,使用无参数构造函数在短时间内创建不同的 Random 对象会创建产生相同随机数序列的随机数生成器。以下示例说明了在短时间内实例化的两个 Random 对象将生成相同的随机数序列…”
为什么不呢?
你需要创建一个实例,因为随机数生成的方式是前面的答案会影响后续的答案。默认情况下,new Random()
构造函数使用当前系统时间来“种子”序列,但这并不是必须的:如果你愿意,可以传入自己的数字。特别地:
var rand = new Random(1234);
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
每次都会产生相同的“随机”数序列。
这意味着Random
类需要保留实例数据(先前的答案或“种子”)以供后续调用使用。
for (int i = 0; i < 1000; i++)
{
Random rand = new Random();
Console.WriteLine(rand.Next(1,100));
}
我会给你一个偏向于范围低端的分布。
这样做:
Random rand = new Random();
for (int i = 0; i < 1000; i++)
{
Console.WriteLine(rand.Next(1,100));
}
将为您提供更好的分发。
随机数生成器必须保持状态才能保证“随机性”。随机数生成器创建的序列是基于随机种子生成的。问题在于计算机中没有真正的随机性。计算机最接近的东西就是系统时钟;这实际上是进程发生的时间。因此,默认情况下使用系统时钟的当前滴答计数。如果您的应用程序足够快,则可能在同一系统滴答下进行许多随机数计算。如果随机数生成器根本不保持状态,则会多次提供相同的随机数(相同的输入产生相同的输出)。这通常不是您想要的。
我知道这个问题已经有答案了,但我必须说我更喜欢在这种情况下使用单例模式。