C#中“静态”Random.Next的正确方法?
为什么我需要创建一个Random类的实例,如果我想创建1到100之间的随机数….就像
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();
不仅它的速度较慢(在一个循环内),它的随机性……根据我不是很好……
来自MSDN:随机类(系统) :
“随机数生成从种子值开始。如果重复使用相同的种子,则生成相同的数字序列。产生不同序列的一种方法是使种子值与时间相关,从而产生不同的序列。 Random的新实例。 默认情况下,Random类的无参数构造函数使用系统时钟生成其种子值 ,而其参数化构造函数可以根据当前时间的滴答数采用Int32值。 但是,因为时钟具有有限分辨率,使用无参数构造函数以紧密连续的方式创建不同的随机对象,创建随机数生成器,生成相同的随机数序列 。以下示例说明了紧密连续实例化的两个随机对象生成相同的随机数序列。 ..”
维基百科解释了PRNG
为什么不?
您需要创建一个实例,因为生成随机数的方式是先前的答案会影响后续答案。 默认情况下, 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
类需要为后续调用保留实例数据(前一个答案或“种子”)。
最好的方法是拥有一个ThreadStatic
Random
实例:
[ThreadStatic] static Random random; Random Get() { if (random == null) random = new Random(Guid.NewGuid().GetHashCode()); return random; }
这照顾一切 。
- 线程安全
- 性能
- 不需要种子
我不知道为什么.NET Framework(以及任何其他地球框架)不会以这种精神使用某些东西。
创建一个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)); }
会给你一个更好的分配。
在C#中创建一个短期实例几乎是免费的。 不要浪费你的时间担心这一点。 您可能有更好的位置来寻找性能或内存增益。
随机数生成器必须保持状态才能“随机”。 随机数生成器创建基于随机种子生成的序列。 问题是计算机中没有任何东西实际上是随机的。 计算机最接近的是系统时钟; 这是该过程发生的有效时间。 因此,默认情况下,使用系统时钟的当前滴答计数。 如果您的应用程序足够快,那么在同一系统滴答下可能会发生许多随机数计算。 如果随机数发生器根本不保持状态,它将多次提供相同的随机数(相同的输入给出相同的输出)。 这通常不是你想要的。
我知道它已经回答了,但我只想说在这种情况下我更喜欢使用单例模式。
我做过一次:
http://www.codeproject.com/Tips/254057/Random-Color-Generator
它使用CIELab色彩距离(人眼最佳之一)来确保容易分辨的颜色。 它有一个observableColor选择你想要远离的颜色(如背景色)加上一个距离因子(其中1是默认值)。
希望能帮助到你…
如果你想要你提到的语法,你需要类似的东西。
namespace MyRandom { public class Random { private static m_rand = new Random(); public static Next(int min, int max) { return m_rand.Next(min, max); } } }
这应该允许你做Random.Next(1,100);
不必担心播种。