确定C#随机实例的种子

时间:2013-07-02 08:01:59

标签: c# random prediction

出于兴趣,我正在玩C#附带的Random类。我试图预测未来。由于它是伪随机的,必须有一些方法来预测数字。到目前为止,我能想到的唯一方法是蛮力(获取所有可能的种子并找到其中随机数的模式),但我相信这将是太多的处理能力,因为种子可以是-2,147,483,647到2,147,483,647。

到目前为止,我已确定:

new Random() == new Random(Environment.TickCount)

并且这两个类将以相同的顺序提供相同的随机数。

以任何可能的方式确定Random类实例的种子吗?如果你可以在实例化Random类时知道Environment.TickCount,可以预测随机数,但我不知道是否可以完成。

2 个答案:

答案 0 :(得分:5)

  

因为它是伪随机的,所以必须有某种方法来预测数字。

实际上;如果你知道内部状态(特别是inextinextpSeedArray - 总共58 int个值,你知道按照确切顺序请求的确切操作(例如,要求Next()Next()NextBytes()与要求Next(),{{1}非常不同},NextBytes()) - 那么你可以做出完全准确的前瞻性猜测。这是种子PRNG的整个 - 它允许可重复的随机性,这在您需要能够重播事件的许多场景中都很有用。

所以:我不认为你可以找回原来的种子,但是为了预测未来(而不是过去)你不会&#39 ; t需要种子 - 你只需要58 Next()个值。

然而!随机性重要的任何内容都应该使用加密随机提供程序 - 那些可重复或可猜测。

例如:

int

答案 1 :(得分:3)

Random的实现不会将种子存储在任何位置 - 而是使用种子数组。所以不幸的是,没有办法确定种子。

带有种子的Random的构造函数如下所示:

public Random(int Seed)
{
    this.SeedArray = new int[0x38];
    int num4 = (Seed == 0x80000000) ? 0x7fffffff : Math.Abs(Seed);
    int num2 = 0x9a4ec86 - num4;
    this.SeedArray[0x37] = num2;
    int num3 = 0x1;
    for (int i = 0x1; i < 0x37; i++)
    {
        int index = (0x15 * i) % 0x37;
        this.SeedArray[index] = num3;
        num3 = num2 - num3;
        if (num3 < 0x0)
        {
            num3 += 0x7fffffff;
        }
        num2 = this.SeedArray[index];
    }
    for (int j = 0x1; j < 0x5; j++)
    {
        for (int k = 0x1; k < 0x38; k++)
        {
            this.SeedArray[k] -= this.SeedArray[0x1 + ((k + 0x1e) % 0x37)];
            if (this.SeedArray[k] < 0x0)
            {
                this.SeedArray[k] += 0x7fffffff;
            }
        }
    }
    this.inext = 0x0;
    this.inextp = 0x15;
    Seed = 0x1;
}

您可以看到它不会将种子存储在任何位置。

(关于这一点的一个奇怪的事情是,由于一些奇怪的原因,它在末尾为Seed变量赋值1 - 但这并不是真正相关的;它只是有点奇怪。)

您可以为Random编写自己的包装类,它保留种子值以供以后检索。实施只记得Seed

public class MyRandom: Random
{
    public MyRandom() : this(Environment.TickCount)
    {
    }

    public MyRandom(int seed) : base(seed)
    {
        this.seed = seed;
    }

    public int Seed
    {
        get { return seed; }
    }

    private readonly int seed;
}