创建一个真正的随机

Kyl*_*yle 15 c# random

可能重复:
为什么我的随机数生成器在C#中不是随机的?
如何用C#生成真正的(非伪)随机数?

我创造了一个骰子游戏,骰子基于百分位数,1-100.

public static void Roll()
{
    Random rand = new Random((int)DateTime.Now.Ticks);
    return rand.Next(1, 100);
}
Run Code Online (Sandbox Code Playgroud)

但我不认为这是基于当前时间的真实随机.

如果我做

for (int i = 0; i < 5; i++)
{
   Console.WriteLine("#" + i + " " + Roll());
}
Run Code Online (Sandbox Code Playgroud)

它们都是相同的值,因为它DateTime.Now.Ticks没有改变,它播种的数字相同.

我想我可以生成一个新的随机种子,如果由于当前时间种子是相同的,但它不像一个诚实的"重新滚动"

我应该怎么做才能尝试复制接近真实/诚实的骰子卷?我应该使用RNGCryptoServiceProvider该类来生成卷吗?

Tim*_*oyd 15

DateTime.Now.Ticks只有大约16ms的分辨率,所以如果你Random在一个16ms的"槽"中多次创建一个带有该过载的它们,它们都将以相同的值被播种,因此你将获得相同的序列.

初始化Random循环外部以便生成单个Random序列,而不是每次在循环内创建它,这可能导致以Randoms相同的值播种,从而生成相同的序列.

更新

我之前的观点是,Random使用CPU ticks 初始化的默认构造函数是不正确的,默认构造函数实际上使用Environment.TickCount,它是:

一个32位有符号整数,包含自上次启动计算机以来经过的时间量(以毫秒为单位).

它的分辨率仍然很低.如果Random快速连续创建多个实例,则可以在同一时隙内轻松创建它们,因此具有相同的种子值,并创建相同的序列.创建一个实例Random并使用它.

更新

除了您的意见之外,如果您希望跨多个线程生成随机序列,请参阅以下Jon Skeet文章,该文章讨论了一个线程安全的包装器:

https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness


T.J*_*der 8

像伪随机数生成器一样Random只能播种一次,所以:

private static Random _rand = new Random();
public static int Roll()
{
    return _rand.Next(1, 100);
}
Run Code Online (Sandbox Code Playgroud)

(注意我做了返回值int而不是void; Roll问题中引用的函数导致语法错误.)

但你的标题是"创造一个真正的随机".Random不会为你做那个,它是一个伪随机数生成器,意味着它是确定性的,如果你不知道种子就很难预测.通常这对于大多数用途来说足够好,但如果你需要真正的随机性,你需要一个熵源.http://random.org是一个受欢迎的.