C# Random.Next()在进行换行之前需要进行多少次迭代?

C# Random.Next()在进行换行之前需要进行多少次迭代?,c#,random,C#,Random,我很确定这永远不会成为问题。然而,我仍然很好奇,在一个给定的种子的作用域完全耗尽并重新生成相同的数字之前,它到底可以生成多少次迭代 例如: 假设您有一个由八个整数索引组成的数组;在给定的迭代过程中,random.Next将用0-31的值填充每个标记。该测试试图了解生成一个包含所有31个元素的完美数组需要多长时间 从数学上讲,每次迭代产生31个完美数组的几率大约为109951162776分之一。然而,这是假设C随机数生成器甚至可以在不自我包装的情况下达到1万亿次迭代的预期范围 那么,总结一下我的实

我很确定这永远不会成为问题。然而,我仍然很好奇,在一个给定的种子的作用域完全耗尽并重新生成相同的数字之前,它到底可以生成多少次迭代

例如:

假设您有一个由八个整数索引组成的数组;在给定的迭代过程中,random.Next将用0-31的值填充每个标记。该测试试图了解生成一个包含所有31个元素的完美数组需要多长时间

从数学上讲,每次迭代产生31个完美数组的几率大约为109951162776分之一。然而,这是假设C随机数生成器甚至可以在不自我包装的情况下达到1万亿次迭代的预期范围

那么,总结一下我的实际问题,随机类是否能达到我给出的测试?或者,它是否会达到一半,而不管经过多少次迭代,它都注定要失败?在随机数生成器结束之前,迭代的次数到底是多少?我还想提到的是,成功生成一个包含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个数组的范围。我的电脑每分钟都会填满我的阵列383500572。看起来这个测试比我原先预计的要长得多

2小时更新

##### Report #####
Elapsed Simulation Time: 02:00:00.4483950
Total Iterations: 55655726300
Success: 0
Failure: 55655726300
##### End Report #####

我有点希望我能把这个线程化…也许可以把时间缩短一半…

已经有足够的评论了。以下是明确的答案

第一:RNG最多只能对64位值进行操作。有有限多个64位值,因此,根据鸽子洞原理,经过足够多的迭代n>2^64,您肯定会得到至少一个重复值

底层算法使用一些有限的、任意数量的参数来决定下一个随机值。如果我们假设有N个状态变量,每个变量有64位,那么最多可以有2^64^N个不同的内部状态。像以前一样,经过足够的迭代,您的RNG将具有相同的内部状态。这将导致一个循环,它肯定会在某个时间点通过。至于循环需要多少次迭代,只需说,每天生成随机数所需的迭代次数将超过您所需的次数。我还没有遇到过这样的循环,它在我的i7cpu上已经连续生成了20分钟,如果你的代码生成了那么多的数字,那么你可能是做错了什么

第二:我不知道连续8个31,但这只是一个特例。基本上,您要问的是:给定一些任意序列的数字S_查询,RNG会生成S_查询吗


为了回答这个问题,我们必须首先注意,RNG生成一个有限的数字序列S_RNG。所以真正的问题是:SU查询是SU RNG的子序列吗?由于S_RNG是有限的,它只能有有限多个子序列。但是,有无限多个可能的S_查询可供选择,因此对于每个RNG,您可以找到一些该RNG无法生成的S_查询。至于8-31的特殊情况,我不知道,我也不知道。保持代码运行并找出答案。

我只是想发布我的测试代码并解释一些事情。首先,这是我的代码:

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++;
            }
        }
    }
}
我当时没有把它编码出来打印出来,但打印出来意味着有50253021875个个人呼叫Random.NextInt;这意味着该决议一直拖延到500亿个电话


而另一个7-Perfect是在程序运行30秒后才出现的。这意味着有很好的种子可以很快获得这种稀有品种。我还测试了30分钟的7个完美指数,但一个也没有得到。这是基于运气,但同时我深深地感觉到好像有一个无形的门槛;如果你不马上击中它,它根本不会发生。上面的海报上写着随机类的分辨率是281474976710656。但我的测试似乎得出结论,决议实际上可能远远小于这一点。你自己试试看,在几秒钟内从4-6个指标开始,然后上升到7和8。不仅仅是概率增加了,还有一个临界点……或者我错了。谁知道呢?

你是在假设它确实围绕着你。你怎么知道它会绕过去呢?它最终会绕过去的,因为它可能是唯一问题的重复,唯一的问题是你的意思
用包裹。如果你的意思是,内部状态在n次迭代后是相同的,那么看看Dickinson发布的链接。如果你想知道,它能产生唯一的数字多长时间。。。好吧,如果它是一个好的PRNG的一半,它应该能够产生重复,有时甚至在随后的两次调用中。显然,相对于引用的算法,实现中的错误可以减少周期性:我感谢你的回答,但我的问题是一个非常顽固的问题,在环绕发生之前有多少次迭代;它能达到我创建的测试吗?答案声称它最多只能达到2^64。链接显示它最多是2^48。@TaW我并没有声称它是,我只是说它必须扭曲。除了它在某个时间点起作用,而且它在未来太遥远而无关紧要之外,我不主张任何东西。从计算机工程的角度来看,这无关紧要。这正是我和计算机科学家相处不好的原因。花费太多时间在太多不重要的细节上。重新阅读后,你会发布声明“经过足够多的迭代n>2^64,你肯定会得到至少一个重复值”。可能是关于价值观的,这些价值观并不重要;环绕的问题是关于内部状态的。它也存储在一个有限的数字中——而且:如果你考虑一些应用程序,比如交易卡,这个数字似乎太高而不重要。一旦你进入其他领域,比如统计模拟,他们将很快获得相当多的重要性。Tsk,Tsk,工程师-@我会把你留给你的统计模拟,然后去处理我的牌。这已经足够好了,因为它在99.9%的时间里都能工作,而大多数人甚至不会注意到其中的差别。
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 ##