在 C# 中获得 0.5% 的机会

Lia*_*age 3 c# random

当我刚接触 C# 时,我真的不想长时间使用 Random() 来尝试得到我想要的东西,而且我也想知道它做了我需要它做的事情,而不需要花很长时间测试的时间量。我怎样才能用随机数得到 0.5% 的概率(1/200)?这段代码会吗?随机到底有多随机……这不是“随机有多随机”的问题,所以不要发布重复项,而是我如何做到这一点的问题。

我的问题不是“随机性如何,而是这段代码是否是完成这项工作的最佳方式,以及它能否实现我想要实现的目标。”

var random = new Random();
var randomNumber = random.Next(1, 200);

if (randomNumber == 87)
{
    // I can put any number inbetween 1 and 200, will this work?
    // If we reach this if statement we have got a 0.5 chance?
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*son 5

首先,您应该将机会转换为 0.0 到 1.0 之间的标准化值。这是概率的数学概念。

对于你的情况,这会给你double probability = 0.005;

然后您可以执行以下操作:

if (rng.NextDouble() < probability)
{
    ...
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为Random.NextDouble()返回一个在半开区间内均匀分布的随机数[0.0, 1.0)(即最多但不包括1.0。)

因此,如果您的概率是,0.0则 的主体if将永远不会被执行,而如果您的概率是1.0,则它将始终被执行。

使用归一化概率的优点是它适用于任何概率,而不仅仅是积分概率。

如果您碰巧有百分比概率,则可以非常简单地将其转换为标准化概率 - 通过将其除以100.0


附录:

使用它Random.Next(int min, int max)几乎没有什么好处,因为它只适用于积分概率。在幕后,Random.Next(int min, int max)是这样实现的:

public virtual int Next(int minValue, int maxValue) {
  if (minValue>maxValue) {
      throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue"));
  }
  Contract.EndContractBlock();

  long range = (long)maxValue-minValue;
  if( range <= (long)Int32.MaxValue) {  
      return ((int)(Sample() * range) + minValue);
  }          
  else { 
      return (int)((long)(GetSampleForLargeRange() * range) + minValue);
  }
}
Run Code Online (Sandbox Code Playgroud)

NextDouble()实现为:

public virtual double NextDouble() {
    return Sample();
}
Run Code Online (Sandbox Code Playgroud)

请注意,这两个实现都调用Sample().

最后我只想指出,内置的 Random 类并不是特别好 - 它的周期不是很长。我使用基于 128 位XOR 移位的 RNG ,它速度非常快,并且生成非常“好的”随机数。

(我使用一个基于此 XORSHIFT+ 生成器的生成器。)