C# 数字 概率[q]/=比率; //重新缩放所有概率,使其总和为1 双重概率=0; probabilities.ToList().ForEach(d=>sumProbabilities+=d); 对于(int i=0;i

C# 数字 概率[q]/=比率; //重新缩放所有概率,使其总和为1 双重概率=0; probabilities.ToList().ForEach(d=>sumProbabilities+=d); 对于(int i=0;i,c#,algorithm,random,C#,Algorithm,Random,数字 概率[q]/=比率; //重新缩放所有概率,使其总和为1 双重概率=0; probabilities.ToList().ForEach(d=>sumProbabilities+=d); 对于(int i=0;i

数字 概率[q]/=比率; //重新缩放所有概率,使其总和为1 双重概率=0; probabilities.ToList().ForEach(d=>sumProbabilities+=d); 对于(int i=0;i请参见以下生成正态分布的函数:您将如何使用它?C#
Random
提供了相当均匀的分布,但Random是随机的-获得“1,1,1,1”的变化与获得“82,37,41,55”的机会相同。如果您想要更均匀的东西,那么您可能需要生成从1到X的范围,然后洗牌这个数组。3-3-3-3的随机性并不比任何其他特定的序列差。下面是我对你的问题的看法:众所周知,如果一个未经训练的人试图模拟掷骰子的序列,那么他们产生的序列将不会是随机的,因为它会避免你所问的场景关于这并不意味着它们的顺序是确定的。远非如此。实际上,您正在询问如何模拟试图模拟掷骰子的人。如果是这样,这是一个有趣的问题,没有明显的答案。因此,在每一个6人组中没有重复,只有在下一个6人组中。但它使采样在某种程度上是可预测的——如果你知道你在区块的第5位,并且知道以前的样本,你可以绝对肯定地预测下一个样本。非常感谢你的贡献。它工作得很好。我已经做了一些修改,最终得到了一个完美的答案——很快我会将此作为另一个答案发布。@Arek很棒!期待着看到它
using System;
using System.Linq;
using MathNet.Numerics.Random;
using MathNet.Numerics.Distributions;

namespace EqualizedSampling
{
    class Program
    {
        static void Main(string[] args)
        {
            int increment         = 10; // how much inverse probabilities are updated per sample
            int guidanceParameter = 1000000; // Small one - consequtive sampling is more affected by outcome. Large one - closer to uniform sampling

            int[]    invprob = new int [6];
            double[] probabilities = new double [6];

            int[] counter = new int [] {0, 0, 0, 0, 0, 0};
            int[] repeat  = new int [] {0, 0, 0, 0, 0, 0};
            int prev = -1;
            for(int k = 0; k != 100000; ++k ) {
                if (k % 60 == 0 ) { // drop accumulation, important for low guidance
                    for(int i = 0; i != 6; ++i) {
                        invprob[i] = guidanceParameter;
                    }
                }
                for(int i = 0; i != 6; ++i) {
                    probabilities[i] = 1.0/(double)invprob[i];
                }
                var cat = new Categorical(probabilities);
                var q = cat.Sample();
                counter[q] += 1;
                invprob[q] += increment;
                if (q == prev)
                    repeat[q] += 1;
                prev = q;
            }
            counter.ToList().ForEach(Console.WriteLine);
            repeat.ToList().ForEach(Console.WriteLine);
        }
    }
}
16670
16794
16713
16642
16599
16582
2431
2514
2489
2428
2367
2436
16675
16712
16651
16677
16663
16622
2745
2707
2694
2792
2682
2847
16659
16711
16618
16609
16750
16653
2184
2241
2285
2259
2425
2247
3, 5, 3, 3, 3, 3, 0, 3, 3, 5, 5, 5, 2, 1, 3, 5, 3, 3, 2, 3, 1, 0, 4, 1, 5, 1, 3, 5, 1, 5, -

Number of occurences:
2
5
2
12
1
8

Max occurences in a row:
1
1
1
4
1
3

Max length where this number did not occur:
14
13
12
6
22
8
4, 1, 5, 3, 2, 5, 0, 0, 1, 3, 2, 4, 2, 1, 5, 0, 4, 3, 1, 4, 0, 2, 4, 3, 5, 5, 2, 4, 0, 1, -

Number of occurences:
5
5
5
4
6
5

Max occurences in a row:
2
1
1
1
1
2

Max length where this number did not occur:
7
10
8
7
10
9
4, 5, 2, 0, 3, 1, 4, 0, 1, 5, 2, 3, 4, 3, 0, 2, 5, 1, 4, 2, 5, 1, 3, 0, 2, 4, 5, 0, 3, 1, -

Number of occurences:
5
5
5
5
5
5

Max occurences in a row:
1
1
1
1
1
1

Max length where this number did not occur:
8
8
7
8
6
7
using System;
using System.Linq;

namespace EqualizedSampling
{
    class Program
    {
        static Random rnd = new Random(DateTime.Now.Millisecond);

        /// <summary>
        /// Returns a random int number from [0 .. numNumbers-1] range using probabilities.
        /// Probabilities have to add up to 1.
        /// </summary>
        static int Sample(int numNumbers, double[] probabilities)
        {
            // probabilities have to add up to 1
            double r = rnd.NextDouble();
            double sum = 0.0;

            for (int i = 0; i < numNumbers; i++)
            {
                sum = sum + probabilities[i];
                if (sum > r)
                    return i;
            }

            return numNumbers - 1;
        }

        static void Main(string[] args)
        {
            const int numNumbers = 6;
            const int numSamples = 30;

            // low ratio makes everything behave more random
            // min is 1.0 which makes things behave like a random number generator.
            // higher ratio makes number selection more "natural"
            double ratio = 5.0;

            double[] probabilities = new double[numNumbers];

            int[] counter = new int[numNumbers];        // how many times number occured
            int[] maxRepeat = new int[numNumbers];      // how many times in a row this number (max)
            int[] maxDistance = new int[numNumbers];    // how many samples happened without this number (max)
            int[] lastOccurence = new int[numNumbers];  // last time this number happened

            // init
            for (int i = 0; i < numNumbers; i++)
            {
                counter[i] = 0;
                maxRepeat[i] = 0;
                probabilities[i] = 1.0 / numNumbers;
                lastOccurence[i] = -1;
            }

            int prev = -1;
            int numRepeats = 1;

            for (int k = 0; k < numSamples; k++)
            {
                // sample next number
                //var cat = new Categorical(probabilities);
                //var q = cat.Sample();
                var q = Sample(numNumbers, probabilities);
                Console.Write($"{q}, ");

                // affect probability of the selected number
                probabilities[q] /= ratio;

                // rescale all probabilities so they add up to 1
                double sumProbabilities = 0;
                probabilities.ToList().ForEach(d => sumProbabilities += d);
                for (int i = 0; i < numNumbers; i++)
                    probabilities[i] /= sumProbabilities;

                // gather statistics
                counter[q] += 1;
                numRepeats = q == prev ? numRepeats + 1 : 1;
                maxRepeat[q] = Math.Max(maxRepeat[q], numRepeats);
                lastOccurence[q] = k;
                for (int i = 0; i < numNumbers; i++)
                    maxDistance[i] = Math.Max(maxDistance[i], k - lastOccurence[i]);
                prev = q;
            }

            Console.WriteLine("-\n");
            Console.WriteLine("Number of occurences:");
            counter.ToList().ForEach(Console.WriteLine);

            Console.WriteLine();
            Console.WriteLine("Max occurences in a row:");
            maxRepeat.ToList().ForEach(Console.WriteLine);

            Console.WriteLine();
            Console.WriteLine("Max length where this number did not occur:");
            maxDistance.ToList().ForEach(Console.WriteLine);

            Console.ReadLine();
        }
    }
}