【问题标题】:Generate Random number between two number with one rare number用一个稀有数字在两个数字之间生成随机数
【发布时间】:2011-04-27 09:05:34
【问题描述】:

我可以使用这个在c中的两个数字之间生成随机数..

arc4random()%(high-low+1)+low;

那么现在我的要求是……我想让一个数字变得稀有……这意味着如果

高=5, 低=1, 和稀有=3,

比 1、2、4 和 5 出现的次数要少得多...

谢谢

【问题讨论】:

  • 我敢打赌这家伙在网上赌场工作:)
  • nop...我为比赛 3 拼图工作..
  • 您也可能对 gamedev.stackexchange.com 感兴趣 :)

标签: c random


【解决方案1】:

让我们来看看这个。首先,我们使用 srand() 函数为随机发生器播种。基本上,计算机可以根据输入 srand() 的数字生成随机数。如果您给出相同的种子值,那么每次都会生成相同的随机数。

因此,我们必须为随机发生器播种一个始终在变化的值。我们通过使用 time() 函数将当前时间的值提供给它来做到这一点。

现在,当我们调用 rand() 时,每次都会产生一个新的随机数。

#include<stdio.h>
int random_number(int min_num, int max_num);

int main(void) {
    printf("Min : 1 Max : 30 %d\n",random_number(0,5));
    printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
    return 0;
}

int random_number(int min_num, int max_num)
{
    int result=0,low_num=0,hi_num=0;
    if(min_num<max_num)
    {
        low_num=min_num;
        hi_num=max_num+1; // this is done to include max_num in output.
    }else{
        low_num=max_num+1;// this is done to include max_num in output.
        hi_num=min_num;
    }

    srand(time(NULL));
    result = (rand()%(hi_num-low_num))+low_num;
    return result;
}

【讨论】:

    【解决方案2】:

    您可以使用表格来计算您的最终掷骰,类似于笔和纸 RPG 进行相同类型的计算:

    Roll 1 D 21(很可能带有代码)。

    • 如果得到 1-5,则算作 1
    • 如果你得到 6-10,则算作 2
    • 如果你得到 11-15,则算作 4
    • 如果你得到 16-20,则算作 5
    • 如果你得到 21,它算作 3

    此选项的优点是您对正在处理的确切概率有很强的了解。您可以准确了解每个数字的稀有或常见程度,并且可以细粒度地控制每个数字与其他数字相比的常见程度。

    您也可以使用分数来生成表格。使用Least Common Multiple 确定共同碱基。该基数是您需要的最大随机数大小。然后,将所有分数放在类似的术语中。使用生成的分子来确定表中每个数字的范围大小。

    使用此自动化解决方案,输入数字之间的关系非常容易理解。例如:

    • 1/4 为 1
    • 1/4 为 2
    • 1/4 换 4
    • 1/5 换 5
    • 1/20 为 3

    这将生成一个像这样的表:

    LCM = 20

    • 1-5 = 1(类似条款 - 5/20)
    • 6-10 = 2 (5/20)
    • 11-15 = 4 (5/20)
    • 16-19 = 5 (4/20)
    • 20 = (1/20)

    关于 LCM 的更多信息:http://en.wikipedia.org/wiki/Least_common_multiple

    【讨论】:

      【解决方案3】:

      所有概率的总和必须为 1。现在我们在这里处理有限范围内的离散概率,因此我们正在查看(这里)5 种具有某种分布的可能性,称它们为 p1、p2、p3、p4 和p5之和为1。

      f0 = 0 f1 = p1 f2 = f1 + p2 f3 = f2 + p3 f4 = f3 + p4 f5 = f4 + p5 且必须为 1

      生成一个从 0 到 1 的随机数,我们将假设它不能正好是 1。查看适合其上限的 f 值,这就是您的随机事件的值。所以也许

      f1 = 0.222 f2 = 0.444 f3 = 0.555 f4 = 0.777 f5 = 1

      如果您的随机数是 0.645,那么您已经生成了 4 事件。 使用上述方法,您产生 3 的机会是其他任何人的一半。我们可以降低它的可能性,例如:

      f1 = 0.24 f2 = 0.48 f3 = 0.52 f4 = 0.76 f5 = 1

      可能是其他人的 0.24,只有 0.04 的 3。

      【讨论】:

      • 这个解决方案看起来很有希望,但你的解释令人困惑。您能解释一下您确定选择哪个值的方式吗?我喜欢这个答案的原因是您可以最大限度地减少所涉及的计算(随机值总是在 0.0 和 1.0 之间生成),并且您只需要为每种结果类型存储一个值。
      • 这很优雅,但需要双精度数和对截止值集的二进制搜索。不是世界末日,而是性能考虑。不过,双精度数在另一个方面也不错 - 比 Merlyn 方法的常见倍数计算更容易设置和理解。
      • 是的,它会比较慢,一个更快的方法是创建一个静态表。也许我们在静态表中有 256 个值,每个值都包含一个从 1 到 5 的数字,然后您从 0 到 255 中选择一个随机数,然后在表中查找它与什么值相关。
      【解决方案4】:
      while true
          generate a random number
              if it's not the rare number, return it
          generate a second random number - say from 1 to 100
          if that second number's <= the percentage chance of the rare number compared to the others, return the rare number
      

      注意:这对于常见情况或返回非稀有数字来说很快。

      【讨论】:

        【解决方案5】:

        您可以根据概率创建一个包含数字的数组:

        list = (1, 1, 2, 2, 3, 4, 4, 5, 5);
        return list.itemAtIndex(random() % list.count());
        

        这不是很优雅,但是如果概率变得更复杂,它可以工作并且很容易扩展。

        【讨论】:

        • +1;这是实现我上面的解决方案的一种方法,如果存储最终很低,不是问题,或者是一个很好的权衡与 CPU 时间
        【解决方案6】:

        一个简单易懂的选项:

        • 生成一个数字以确定是否要返回稀有数字(例如,生成一个 [0-99] 范围内的数字,如果为 0,则返回稀有数字
        • 如果您执行此步骤,您将返回一个非稀有数字:继续生成正常范围内的数字,直到您获得任何非稀有数字,然后返回该数字

        还有其他替代方法只需要您生成一个数字,但上面感觉它是最容易编写和理解的方法。

        【讨论】:

        • 第二步不需要重复生成数字,只需将范围减一,如果随机数>=稀有数字,则加一。
        • @Skizz:你当然可以这样做,是的。会更有效率。我认为这需要更多的大脑周期,而不仅仅是重复——至少对我来说是这样——但这仍然是一个好主意。
        猜你喜欢
        • 1970-01-01
        • 2014-12-19
        • 2014-10-02
        • 2015-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多