【问题标题】:Is there a better way to calculate odds?有没有更好的方法来计算赔率?
【发布时间】:2017-10-12 15:13:26
【问题描述】:

我正在编写一个名为 Club Keno 的模拟彩票游戏的程序,我想匹配他们对 Kicker 的赔率。所以我所做的是选择一个介于 1 和 10046 之间的随机数,然后根据该数字,我返回 kicker 值。如果随机数是 1000,我会返回 4 的 kicker 值。我想知道是否有更好的方法来做到这一点。而且我意识到它加起来并不完全是 100%,但这是我可以在网上找到的几率。他们加起来高达 100.45%

public static int Kicker()
{
    var rnd = new Random();
    int num = rnd.Next(1, 10046);

    if (num < 125) //1.25 percent chance
        return 10;
    if (num < 495) //3.7 percent chance
        return 5;
    if (num < 1120)//6.25 percent chance
        return 4;
    if (num < 1745)//6.25 percent chance
        return 3;
    if (num < 5745)//40 percent chance
        return 2;

    return 1; // 43 percent chance
}

【问题讨论】:

  • 为什么是 10046?为什么要使用 int 呢?您可以从随机生成双精度。另外,为什么你的随机实例在方法中?它应该是静态和类级别,而不是方法级别。
  • 它在一个名为 Pick 的类中,该类负责选择抽奖号码、玩家号码、Jack 号码、ez 选择号码和起脚号码。
  • .... 因为否则,如果您非常快速地调用此方法(因为当前时间用作 Random 的种子),您将始终生成相同的“随机”数字。
  • @JosephThompson 使用Thread.Sleep 来克服相同的随机种子真是太可怕了。
  • 老实说,只需使用 this answer 并调整您的代码以适应。使用Dictionary&lt;int, double&gt;(而不是 OP 使用的自定义类)来存储您的“踢球者”及其概率。大约需要 5 分钟

标签: c#


【解决方案1】:

如何为 Random 类使用扩展方法:

static T Pick<T>(this Random random, Dictionary<T, double> elementToProbability) 
{
    var totalProbability = elementToProbability.Values.Sum();
    var randomValue = random.NextDouble() * totalProbability;

    foreach (var keyValuePair in elementToProbability) 
    {
        if (randomValue < keyValuePair.Value) 
            return keyValuePair.Key; 

        randomValue -= keyValuePair.Value;
    }
    return default(T); 
}

然后像这样使用它:

Random rnd = new Random();
int num = rnd.Pick(new Dictionary<int, double> 
{
    { 10, 1.25 },
    { 5, 3.7 },
    { 4, 6.25 },
    { 3, 6.25 },
    { 2, 40 },
    { 1, 43 }
});

请注意,“概率”之和不必等于 1 或 100 或任何特定值。

【讨论】:

  • 我花了一段时间才弄清楚如何实现这个(因为我对扩展方法还很陌生),但现在我一直在试图弄清楚如何返回一个值。当我尝试返回随机时,它说“无法将类型 System.Random 隐式转换为 Int。
  • 嗯,“当我尝试返回随机时”是什么意思?你想使用的方式如下:var rnd = new Random(); int num = rnd.Pick(new Dictionary&lt;int, double&gt; { ... });
  • 哦,好的,知道了。我没有给它分配一个数字,我只是在使用它。谢谢!效果很好!!!
【解决方案2】:

我查看了club-keno 的页面以查看其中所述的可能性,如果您想获得准确的实施,那么这里是我的发现和建议。

首先,上述赔率有些不准确,因为如前所述,所有可能结果的概率加起来并不等于 1.0。然而,底线的陈述“总赔率:1.74 中的 1”暗示了一些东西:这是没有得到 1 的赔率。事实证明,它是数字 2 到 10 的单独赔率的相当准确的总和。所以,如果我们认为这是正确的,那么得到 1 的几率实际上是 2.35081 中的 1。

因此,我计算出要在代码中(几乎)准确地表示它们,那么我们需要在 100,000 中表示以下赔率

  • 1:42546
  • 2:40000
  • 3:6250
  • 4:6250
  • 5:3704
  • 10:1250

所以代码应该是这样的:

var rnd = new Random();
:
public static int Kicker()
{
  // get integer number in the range 0-99999
  int num = rnd.Next(0, 100000);

  // check the ranges
  if (num < 42546) return 1; // checking for 0 to 42,545
  if (num < 82546) return 2; // 42,546 to 82,545
  if (num < 88796) return 3; // 82,546 to 88,795
  if (num < 95046) return 4; // 88,796 to 95,045
  if (num < 98750) return 5; // 95,046 to 98,749
  return 10;                 // 98,750 to 99,999
}

当然,我们相信随机数生成器的概率分布在整个数字范围内都是平坦的。如果您怀疑不是,那么您可以通过例如使用更大的随机数范围(例如大小的 100 倍,然后在应用测试之前对结果取模 100000)来在一定程度上缓解:

int num = rnd( 0, 10000000 ) % 100000 ;

【讨论】:

    猜你喜欢
    • 2020-04-17
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多