【问题标题】:Implement "percent chance" in C#在 C# 中实现“百分比机会”
【发布时间】:2016-10-17 22:23:38
【问题描述】:

我需要一些关于 C# 代码中的百分比机会的帮助。假设我有从 1 到 100 的 for 循环,在那个循环中我有一个“if”代码,我想执行 70% 次(随机)。我将如何实现这一目标?所以是这样的:

static void Main(string[] args)
{
    var clickPercentage = 70;

    for (int i = 0; i < 100; i++)
    {
        if (chance)
        {
            //do 70% times
        }
    }
}

因此,对于顶级示例,我希望代码以 70% 的机会被击中,对于我的示例来说,大约是 70 次。

我尝试过的事情:(远不及 70%,更像是 1% 或 2% 的机会)

static void Main(string[] args)
{
    var clickPercentage = 70;

    for (int i = 0; i < 100; i++)
    {
        var a = GetRadnomNumber(1, clickPercentage);
        var b = GetRadnomNumber(1, 101);

        if (a <= b)
        {
            Console.WriteLine($"Iteracija {i} - {b} <= {a}");
        }
    }
}

public static int GetRadnomNumber(int min, int max)
{
    var random = new Random();
    var retVal = random.Next(min, max);

    return retVal;
}

【问题讨论】:

标签: c# asp.net random


【解决方案1】:

使用Random class

您可以使用Random.Next(100) 获得介于 0 和 99 之间的随机 int

public static Random RandomGen = new Random();
.....

int clickPercentage = 70;
for (int i = 0; i < 100; i++)
{
    int randomValueBetween0And99 = RandomGen.Next(100);
    if (randomValueBetween0And99 < clickPercentage)
    {
        //do 70% times
    }
}

重要的是您不要在循环中创建随机实例,因为它的默认构造函数使用当前时间作为种子。这可能会导致循环中的重复值。这就是我使用static 字段的原因。您还可以将Random 实例传递给方法,以确保调用者对生命周期和种子负责。有时使用相同的种子很重要,例如重复相同的测试。

【讨论】:

    【解决方案2】:

    把它包装成一个函数:

    private static Random generator = null; 
    
    /*
     *  Calls onSuccess() chanceOfSuccess% of the time, otherwise calls onFailure() 
     */
    public void SplitAtRandom(int chanceOfSuccess, Action onSuccess, Action onFailure)
    {
        // Seed
        if (generator == null)
            generator = new Random(DateTime.Now.Millisecond);
    
        // By chance
        if (generator.Next(100) < chanceOfSuccess)
        {
            if (onSuccess != null)
                onSuccess();
        }
        else
        {
            if (onFailure != null)
                onFailure();
        }
    }
    

    并使用它:

    for (int i = 0; i < 100; i++)
    {
        SplitAtRandom(70, 
                      () => { /* 70% of the time */ }, 
                      () => { /* 30% of the time */ });
    } 
    

    【讨论】:

      【解决方案3】:

      不太确定您的逻辑,但快速浏览一下,您正在循环中创建一个随机对象。

      问题在于Random 类使用当前时间作为种子。如果种子相同,Random 类将产生相同的随机数序列。由于现在的 CPU 速度非常快,因此通常会发生多次循环迭代具有完全相同的种子,因此,随机数生成器的输出将是完全可预测的(并且与之前的输出相同)。

      为避免这种情况,只需创建一次 Random 类的实例并在您的代码中重用它,类似于

      private static readonly Random _rnd = new Random();
      // use _rnd in you code and don't create any other new Random() instances
      

      【讨论】:

      • 正在阅读有关随机实例的信息,是的,我确实有很多相同的“随机”数字并没有意识到这是个问题。
      【解决方案4】:

      基本上,每次迭代都不需要新的Random-instance。简单使用这个:

      var r = new Random();
      
      for(int i = 0; i < 100; i++)
      {
          var p = r.Next(100);
          if (p >= 1 - myThreshhold) // do anything in 70% of cases
      }
      

      您也可以使用if (p &lt;= myThreshold)

      【讨论】:

        猜你喜欢
        • 2022-01-20
        • 1970-01-01
        • 1970-01-01
        • 2021-01-19
        • 2020-03-09
        • 2021-02-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多