出于兴趣,我正在玩C#附带的Random类。我试图预测未来。由于它是伪随机的,必须有一些方法来预测数字。到目前为止,我能想到的唯一方法是蛮力(获取所有可能的种子并找到其中随机数的模式),但我相信这将是太多的处理能力,因为种子可以是-2,147,483,647到2,147,483,647。
到目前为止,我已确定:
new Random() == new Random(Environment.TickCount)
并且这两个类将以相同的顺序提供相同的随机数。
以任何可能的方式确定Random类实例的种子吗?如果你可以在实例化Random类时知道Environment.TickCount,可以预测随机数,但我不知道是否可以完成。
答案 0 :(得分:5)
因为它是伪随机的,所以必须有某种方法来预测数字。
实际上;如果你知道内部状态(特别是inext
,inextp
和SeedArray
- 总共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;
}