从数字范围滑动加权随机化?

时间:2017-12-29 01:34:03

标签: ruby random

从一个范围中挑选一个随机数时,我正在rand(0..100)。这一切都很好,但我希望它支持范围的低端。

因此,根据一些加权比例,选择0的概率最高,挑选概率100(以及之间的所有内容)的概率最低。

我如何在Ruby中实现它?

3 个答案:

答案 0 :(得分:2)

您可以尝试使用两个随机数中的较低者。这将有利于较小的数字。

[rand(0..100), rand(0..100)].min 

如果您的第一个数字是5,那么第二个数字较低(和替换)的可能性仅为4中的4个。

如果您的第一个号码是95,那么您的第二个号码降低的可能性是94分(满分100分),因此它可能会被较低的号码替换。

答案 1 :(得分:1)

我的回答主要是从基础概率分布中产生随机变量,而不仅仅是那些给较小随机变量赋予更大权重的分布。

您需要识别具有所需形状的(概率)密度函数f。然后构造它的(累积)分布函数F和后者的反函数G分位数),意味着所有G(F(x)) = x的{​​{1}}样本空间。 x可以是连续的或离散的。

例如,ff可以是(负)指数密度和分布函数,它们对较小的值赋予较高的权重,如下所示(来源:Wiki for Exponential Distribution)。

Exponential PDF Exponential CDF

指数PDF 指数CDF

这些函数分别由f(x)=λe-λx和F(x)= 1 - e -λx给出,其中F是自然对数的基础。 e形状参数

要为此分布生成随机变量,我们将绘制一个介于0和1之间的(伪)随机数,在CDF图的垂直轴上标记该伪随机数并从该点绘制一条水平线。随机变量是水平轴上CDF与水平线相交的点。如果y是0到1之间的随机数,我们有

λ

解决y = 1 − e**(−λx)

x

因此反向CDF被视为

x = -log(1 - y)/λ

以下是g(y) = -log(1 - y)/λ 的一些随机变量。

λ = 1

大多数CDF没有封闭形式的反函数,但如果CDF是连续的,则可以执行二进制搜索来计算随机变量(图上的def g(y) -Math.log(1 - y) end 5.times { y = rand; puts "y = #{y.round(2)}, x = #{g(y).round(2)}" } y = 0.09, x = 0.10 y = 0.67, x = 1.09 y = 0.35, x = 0.43 y = 0.55, x = 0.79 y = 0.19, x = 0.21 )的任意近似近似值。给定x

Weibull Distribution是为数不多的具有闭式反函数的连续分布(除了均匀和三角形之外)。有两个参数,它提供了比单参数指数分布更大的范围,用于建模所需的形状。

对于离散CDF,可以使用y = rand语句(或者更好的是case语句)来计算给定if的随机变量。

答案 2 :(得分:0)

我会做这样的事情:

weighted_range

这将给出:

  • 1 最高被挑选的概率,因为它在weighted_range数组中出现100次,
  • 2 被选中的第二高概率,因为它在weighted_range数组中出现99次,
  • 100 最低被挑选的概率,因为它只会在weighted_range数组中出现一次,并且
  • 99 被选中的第二低概率,因为它会在low_end_of_range数组中出现两次,

如果您不需要采样大小的任何灵活性(即high_end_of_range / (1..100).map { |i| (101 - i).times.map { i } }.flatten.sample ),您可以在一个漂亮的单行中进行:

wait_time