增加从数组中选择名称的几率

本文关键字:几率 选择 数组 增加 | 更新日期: 2023-09-27 18:21:55

对于我的程序,我已经提示用户将20个名称放入一个数组中(目前测试的数组大小为5),然后将此数组发送到一个文本文档中。我需要制作它,这样它就会从列表中随机选择一个名字并显示它(我已经这样做了)。但我现在需要让它增加名字被选中的机会,我该怎么做?

例如。我想增加从数组中选择"Jim"这个名字的机会。

class Programt
{
    static void readFile()
    {
    }
    static void Main(string[] args)
    {
        string winner;
        string file = @"C:'names.txt";
        string[] classNames = new string[5];
        Random RandString = new Random();
        Console.ForegroundColor = ConsoleColor.White;
        if (File.Exists(file))
        {
            Console.WriteLine("Names in the text document are: ");
            foreach (var displayFile in File.ReadAllLines(file))
            Console.WriteLine(displayFile);

            Console.ReadKey();
        }
        else
        {
            Console.WriteLine("Please enter 5 names:");
            for (int i = 0; i < 5; i++)
                classNames[i] = Console.ReadLine();
            File.Create(file).Close();
            File.WriteAllLines(file, classNames);
            Console.WriteLine("Writing names to file...");
            winner = classNames[RandString.Next(0, classNames.Length)];
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("'nThe winner of the randomiser is: {0} Congratulations! ", winner);
            Thread.Sleep(3000);
            Console.Write("Completed");
            Thread.Sleep(1000);
        }
    }
}

增加从数组中选择名称的几率

有两种方法。您可以生成一个以一个数字为目标的正态分布的RNG。

或者更简单的方法是平移步骤。在0-100范围内生成,然后生成以有偏差的方式转换为答案的代码,例如

  • 0-5:答案1
  • 6-10:答案2
  • 11-90:答案3
  • 91-95:答案4
  • 96-100:答案5

这就有80%的机会选择答案3,其他人只有5%的机会选择

因此,在当前有RandString.Next(0, classNames.Length)的情况下,可以用类似GetBiasedIndex(0, classNames.Length, 3) 的函数来替换它

该函数看起来像这样(带有测试代码):

    public Form1()
    {
        InitializeComponent();
        int[] results = new int[5];
        Random RandString = new Random();
        for (int i = 0; i < 1000; i++)
        {
            var output = GetBiasedIndex(RandString, 0, 4, 3);
            results[output]++;
        }
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 5; i++)
        {
            builder.AppendLine(results[i].ToString());
        }
        label1.Text = builder.ToString();
    }

    private int GetBiasedIndex(Random rng, int start, int end, int target)
    {
        //Number between 0 and 100 (Helps to think percentage)
        var check = rng.Next(0, 100);
        //There's a few ways to do this next bit, but I'll try to keep it simple
        //Allocate x% to the target and split the remaining y% among all the others
        int x = 80;//80% chance of target
        int remaining = 100 - x;//20% chance of something else
        //Take the check for the target out of the last x% (we can take it out of any x% chunk but this makes it simpler
        if (check > (100 - x))
        {
            return target;
        }
        else
        {
            //20% left if there's 4 names remaining that's 5% each
            var perOther = (100 - x) / ((end - start) - 1);
            //result is now in the range 0..4
            var result = check / perOther;
            //avoid hitting the target in this section
            if (result >= target)
            {
                //adjust the index we are returning since we have already accounted for the target
                result++;
            }
            //return the index;
            return result;
        }
    }

输出:

52
68
55
786
39

如果你要重复调用这个函数,你需要传入RNG的实例,这样你就不会在每次调用时重置种子。

如果你想以一个名称而不是索引为目标,你只需要首先查找该名称,并在找不到该名称时有一个else条件。