【问题标题】:C++ computing a probability for an eventC++ 计算事件的概率
【发布时间】:2019-08-17 12:08:06
【问题描述】:

我正在尝试模拟野生口袋妖怪遭遇。如公式所述:

The rate of Pokémon encounter is determined from a simple mathematical formula:
1 in (187.5 / ( x )) per step.

Let x equal the a value which determines how rare the Pokémon is. The higher the encounter rate, 
the more common the Pokémon is.

Encounter-rate Table
Encounter type Encounter rate
Very common     10
Common          8.5
Semi-rare       6.75
Rare            3.33
Very rare       1.25

我想在每次按下按钮后运行这个概率。如何用rand() 模拟这个?

【问题讨论】:

  • 我可以说服您使用std::discrete_distribution 代替rand 吗? rand kinda sucks.
  • @user4581301 确定!
  • 遗憾的是,重新阅读时,std::discrete_distribution 并不是适合这项工作的工具。它非常适合加权遭遇,但这并不是您在这里所做的。如果是这样,代码将类似于:ideone.com/Vud9UC

标签: c++ visual-c++ random probability weighted


【解决方案1】:

我会这样做

映射 rand()

rand() / (float)RAND_MAX

Rand() 返回一个从 0 到 RAND_MAX 的值,所以这个公式将 0 -> RAND_MAX 映射到 0 -> 1

(float) 用于使RAND_MAX 成为浮点数,因为rand() 返回的值是int,而c++ 中的int / int 返回int

(rand() / (float)RAND_MAX) * 10 

如果将结果乘以 10,它将映射 rand()0 -> 10

(rand() / (float)RAND_MAX) * 187.5

这将从0 -> 187.5映射rand()

187.5 分之一

我们从0 -> 187.5映射rand()的值

现在每次我们调用rand(),它都会从0->187.5返回一个随机数

为了简化,假设我们从 0 -> 200 映射 rand()

rand() 将有 1/2 的机会返回小于 100 的数字,因为 0 -> 200 之间的每个数字都有相同的返回机会(例如 rand() 可以返回 25.67 或 100.9 或 140.6 )

( (rand() / (float)RAND_MAX) * 187.5 ) < 1

根据同样的原理,返回的数字小于 1 的概率为 1 的 187.5

最终解决方案

我们仍然缺少 187.5 / X

要实现遭遇率,您只需将映射从 0 -&gt; 187.5 更改为

0 -> 187.5 / X

我们可以看到,如果 X 大,则意味着遭遇率高,187.5 变小,返回的数字比 1 更小,但如果遭遇率低,X 变小,187.5 变小更大(小于 1 的可能性更低)

最终代码

srand (time(NULL)); // Init rand() with a seed
bool encountered = ( (rand() /  (float)RAND_MAX) * (187.5 / x) ) < 1

优化

一位用户指出,使用最后一个代码,您需要为每个事件计算 5 个 rand(),但如果我们稍微调整一下公式,您只能计算 1 个 rand()

通过使用简单的数学运算,您可以知道在 10 / 2 步中发生一次 (1) 的事件 是在 (2) 中分 10 步发生两次的事件

因此,在 187.5 / X 步中发生一次 (1) 的事件在 187.5 步中发生 (1 * X)

如果我们从 0 -> 187.5 映射 rand() 那么对于每个 pokemon,我们可以只使用一个 rand() 为其计算一个唯一值

float randomNumber      = (rand() / (float)RAND_MAX) * 187.5
bool encountedPokemon1  = randomNumber < 1 * encounter_rate_first_pokemon
bool encountedPokemon2  = randomNumber < 1 * encounter_rate_second_pokemon

【讨论】:

  • 如果只有一个事件,很好的讨论和工作与rand 的任何事情一样。有 5 个可能的事件。因此,您要么生成五个数字并尝试五次尝试每一步遇到一次,要么您必须做其他事情。
  • 我不想添加这个,因为用户似乎是 C++ 的新手,但既然你指出了这一点,我就会这样做
【解决方案2】:

使用模运算符。 rand() 将返回一个介于 0 和整数可以容纳的最大值之间的数字。所以 rand()%10 将返回一个介于 0 和 9 之间的数字。

(rand()%1875)

如果您还不知道,% 会给您余数。所以 x%10 永远不会大于 9。

这是reference

【讨论】:

  • 谢谢你,但其他概率呢?
  • 您只需输入其他数字,其余代码将相同。
  • 请注意,这也会在一次遭遇中给予五次尝试,每个生物稀有度一次尝试,每一步。这可能不是我们所需要的。
  • @user4581301 好点。您可以存储随机数,然后使用单独的数字范围来比较随机数。
猜你喜欢
  • 2021-04-29
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多