我很确定这永远不会成为问题。但是,我仍然很好奇,确切地说,任何给定的种子在其范围完全耗尽之前会产生一个随机数,并且它会再次生成相同的数字,从而产生多少次迭代?
举个例子:
假设你有一个由8个整数索引组成的数组;在给定的迭代期间,random.Next将为每个indice填充0-31的值。测试试图了解生成31个完美阵列需要多长时间。
在数学上,每次迭代的概率大约是1,099,511,627,776中的1,以产生所有31个的完美阵列。然而,这假设C#随机数生成器甚至可以使其达到1万亿次迭代的预计范围,而不会回绕自身。
那么,总结一下我的实际问题,可以让Random类实现我提出的测试吗?或者它会达到一个中途标记而不管它经历多少次迭代就会失败?随机数生成器结束之前的迭代次数到底是多少?我还想提一下,成功生成6个完美31的数组只需要大约20分钟。我经过测试并验证过。
我还应该提一下,我目前正在运行一个试图实现这一目标的测试机制。到目前为止,这是当前报告,每分钟显示一次:
##### Report #####
Elapsed Simulation Time: 00:49:00.1759559
Total Iterations: 20784834152
Perfect Eight Success: 0
Failure: 20784834152
##### End Report #####
我估计需要时间才能找到一个完美的31个阵列大约47小时和56分钟,以接近找到一个完美的31集的范围。这是我的电脑每分钟填充我的阵列383,500,572。看起来这个测试的时间比我原先预测的要长得多。
2小时更新
##### Report #####
Elapsed Simulation Time: 02:00:00.4483950
Total Iterations: 55655726300
Success: 0
Failure: 55655726300
##### End Report #####
我有点希望自己能做到这一点...可能会把时间缩短一半......
答案 0 :(得分:4)
已经有足够的评论了。这是最终答案。
首先:RNG最多只能运行64位值。存在有限多个64位值,因此,根据鸽子原理,通过足够的迭代(n> 2 ^ 64),您肯定会得到至少一个重复值。
底层算法使用一些有限的,任意数量的参数来决定下一个随机值。如果我们假设有N个状态变量,每个变量具有64位,则最多可以有(2 ^ 64)^ N个不同的内部状态。像以前一样,通过足够的迭代,您的RNG将具有相同的内部状态。这将导致一个循环,它肯定会在某个时间点通过。至于循环回来需要多少次迭代,就足以说明日常的随机数生成需要的还要多。我还没有碰到任何这样的循环(它已经在我的i7 CPU上连续生成了20分钟,如果你的代码生成了那么多数字,你可能会做一些非常错误的事情)。
第二次:我不知道连续八个31,但这只是一个特例。您基本上要问的是:给定一些任意序列S_QUERY的数字,RNG会生成S_QUERY吗?
要回答,我们必须首先注意到RNG生成数字的有限序列S_RNG。所以真正的问题是:S_QUERY是S_RNG的后续序列吗?由于S_RNG是有限的,它只能有有限的许多子序列。但是,有无数可能的S_QUERY可供选择,因此对于每个RNG,您可以找到一些无法由该RNG生成的S_QUERY。至于8个31的特例,我不知道,我也不知道。保持代码运行并找出答案。
答案 1 :(得分:0)
我只想发布我的测试代码并解释一些事情。首先,这是我的代码:
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
public static class Program
{
public static long Success;
public static long Failure;
public static long TotalIterations;
public static long TotalCallsToRandom;
public static readonly int CurrentSeed = Environment.TickCount;
public static Random Random = new Random(CurrentSeed);
public static Stopwatch TotalSimulationTime = new Stopwatch();
public static Stopwatch ReportWatchTime = new Stopwatch();
public static bool IsRunning = true;
//
public const int TotalTestingIndices = 7;
public const int MaximumTestingValue = 31;
public const int TimeBetweenReports = 30000; // Report every 30 Seconds.
//
public static void Main(string[] args)
{
int[] array = new int[TotalTestingIndices];
TotalSimulationTime.Start();
ReportWatchTime.Start();
while (IsRunning)
{
if (ReportWatchTime.ElapsedMilliseconds >= TimeBetweenReports)
{
Report();
ReportWatchTime.Restart();
}
Fill(array);
if (IsPerfect(array))
{
Success++;
Console.WriteLine("A Perfect Array was found!");
PrintArray(array);
Report();
IsRunning = false;
}
else
{
Failure++;
}
TotalIterations++;
}
Console.Read();
}
public static void Report()
{
Console.WriteLine();
Console.WriteLine("## Report ##");
Console.WriteLine("Current Seed: " + CurrentSeed);
Console.WriteLine("Desired Perfect Number: " + MaximumTestingValue);
Console.WriteLine("Total Testing Indices: " + TotalTestingIndices);
Console.WriteLine("Total Simulation Time: " + TotalSimulationTime.Elapsed);
Console.WriteLine("Total Iterations: " + TotalIterations);
Console.WriteLine("Total Random.NextInt() Calls: " + TotalCallsToRandom);
Console.WriteLine("Success: " + Success);
Console.WriteLine("Failure: " + Failure);
Console.WriteLine("## End of Report ##");
Console.WriteLine();
}
public static void PrintArray(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
Console.Write(array[i]);
if (i != array.Length - 1)
{
Console.Write(",");
}
}
}
/// <summary>
/// Optimized to terminate quickly.
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public static bool IsPerfect(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] != MaximumTestingValue)
{
return false;
}
}
return true;
}
public static void Fill(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = Random.Next(MaximumTestingValue + 1);
TotalCallsToRandom++;
}
}
}
}
经过大约三个小时的测试后,我得出了一些实现。我相信它有可能得到8个完美的31指数...但只有你在第一个十亿左右的时候才能在Random.Next()中调用。我知道这似乎是一个主观的说法,但它是我通过这些测试所经历的。我从来没有得过8-Perfect 31,但我确实得到了7-Perfect 31&#39; s。这是13分钟后的第一次。这是打印输出:
A Perfect Array was found!
31,31,31,31,31,31,31
## Report ##
Total Simulation Time: 00:13:32.4293323
Total Iterations: 7179003125
Success: 1
Failure: 7179003125
## End of Report ##
我当时没有将其打印出来进行打印,但是打印输出意味着对Random.NextInt()进行了50,253,021,875次单独调用。这意味着该决议一直持续到 50亿次电话 。
其他7-Perfect仅在程序运行约30秒后才开始。这意味着有好的种子&#34;很快就能获得这种稀有性。我还对7-Perfect指数进行了30分钟的测试,并没有获得单一指数。它基于运气,但与此同时,我感觉好像有一个无形的门槛;如果你不赶快打它,它根本就不会发生。上面的一张海报说,随机类的分辨率是&#34; 281,474,976,710,656&#34;。但我的测试似乎得出结论,分辨率实际上可能远小于此。自己尝试一下,从4-6个索引开始(在几秒钟内发生)并向上移动到7和8.不仅概率增加,还有一个阈值。或许我错了。谁知道?