SimpleRNG is a simple random number generator based on George Marsaglia's MWC (multiply with carry) generator. Although it is very simple, it passes Marsaglia's DIEHARD series of random number generator tests. Written by John D. Cook http://www.johndcook.com
Example #1
0
 public static void Main()
 {
     for (int i = 0; i < 10; i++)
     {
         Console.WriteLine(SimpleRNG.GetUint());
     }
 }
Example #2
0
        static void KSTest()
        {
            /// Kolmogorov-Smirnov test for distributions.  See Knuth volume 2, page 48-51 (third edition).
            /// This test should *fail* on average one time in 1000 runs.
            /// That's life with random number generators: if the test passed all the time,
            /// the source wouldn't be random enough!  If the test were to fail more frequently,
            /// the most likely explanation would be a bug in the code.

            SimpleRNG.SetSeedFromSystemTime();

            int    numReps            = 1000;
            double failureProbability = 0.001; // probability of test failing with normal input
            int    j;

            double[] samples = new double[numReps];

            for (j = 0; j != numReps; ++j)
            {
                samples[j] = SimpleRNG.GetUniform();
            }

            System.Array.Sort(samples);

            double CDF;
            double temp;
            int    j_minus = 0, j_plus = 0;
            double K_plus  = -double.MaxValue;
            double K_minus = -double.MaxValue;

            for (j = 0; j != numReps; ++j)
            {
                CDF  = samples[j];
                temp = (j + 1.0) / numReps - CDF;
                if (K_plus < temp)
                {
                    K_plus = temp;
                    j_plus = j;
                }
                temp = CDF - (j + 0.0) / numReps;
                if (K_minus < temp)
                {
                    K_minus = temp;
                    j_minus = j;
                }
            }

            double sqrtNumReps = Math.Sqrt((double)numReps);

            K_plus  *= sqrtNumReps;
            K_minus *= sqrtNumReps;

            // We divide the failure probability by four because we have four tests:
            // left and right tests for K+ and K-.
            double p_low       = 0.25 * failureProbability;
            double p_high      = 1.0 - 0.25 * failureProbability;
            double cutoff_low  = Math.Sqrt(0.5 * Math.Log(1.0 / (1.0 - p_low))) - 1.0 / (6.0 * sqrtNumReps);
            double cutoff_high = Math.Sqrt(0.5 * Math.Log(1.0 / (1.0 - p_high))) - 1.0 / (6.0 * sqrtNumReps);

            Console.WriteLine("\n\nTesting the random number distribution");
            Console.WriteLine("using the Kolmogorov-Smirnov (KS) test.\n");

            Console.WriteLine("K+ statistic: {0}", K_plus);
            Console.WriteLine("K+ statistic: {0}", K_minus);
            Console.WriteLine("Acceptable interval: [{0}, {1}]", cutoff_low, cutoff_high);
            Console.WriteLine("K+ max at {0} {1}", j_plus, samples[j_plus]);
            Console.WriteLine("K- max at {0} {1}", j_minus, samples[j_minus]);

            if (cutoff_low <= K_plus && K_plus <= cutoff_high && cutoff_low <= K_minus && K_minus <= cutoff_high)
            {
                Console.WriteLine("\nKS test passed\n");
            }
            else
            {
                Console.WriteLine("\nKS test failed\n");
            }
        }
Example #3
0
        // Verify that distributions have the correct mean and variance.
        // Note that sample mean and sample variance will not exactly match the expected mean and variance.
        static void TestDistributions()
        {
            const int   numSamples = 100000;
            double      mean, variance, stdev, shape, scale, degreesOfFreedom;
            RunningStat rs = new RunningStat();

            // Exponential distribution
            rs.Clear();
            mean = 2;
            for (int i = 0; i < numSamples; ++i)
            {
                rs.Push(SimpleRNG.GetExponential(mean));
            }
            PrintResults("exponential", mean, 5, rs.Mean(), rs.Variance());

            // Gamma distribution
            rs.Clear();
            shape = 10; scale = 2;
            for (int i = 0; i < numSamples; ++i)
            {
                rs.Push(SimpleRNG.GetGamma(shape, scale));
            }
            PrintResults("gamma", shape * scale, shape * scale * scale, rs.Mean(), rs.Variance());

            // Normal distribution
            rs.Clear();
            mean = 2; stdev = 5;
            for (int i = 0; i < numSamples; ++i)
            {
                rs.Push(SimpleRNG.GetNormal(2, 5));
            }
            PrintResults("normal", mean, stdev * stdev, rs.Mean(), rs.Variance());

            // Student t distribution
            rs.Clear();
            degreesOfFreedom = 6;
            for (int i = 0; i < numSamples; ++i)
            {
                rs.Push(SimpleRNG.GetStudentT(6));
            }
            PrintResults("Student t", 0, degreesOfFreedom / (degreesOfFreedom - 2.0), rs.Mean(), rs.Variance());

            // Weibull distribution
            rs.Clear();
            shape    = 2; scale = 3;
            mean     = 3 * Math.Sqrt(Math.PI) / 2;
            variance = 9 * (1 - Math.PI / 4);
            for (int i = 0; i < numSamples; ++i)
            {
                rs.Push(SimpleRNG.GetWeibull(shape, scale));
            }
            PrintResults("Weibull", mean, variance, rs.Mean(), rs.Variance());

            // Beta distribution
            rs.Clear();
            double a = 7, b = 2;

            mean     = a / (a + b);
            variance = mean * (1 - mean) / (a + b + 1);
            for (int i = 0; i < numSamples; ++i)
            {
                rs.Push(SimpleRNG.GetBeta(a, b));
            }
            PrintResults("Beta", mean, variance, rs.Mean(), rs.Variance());
        }