【发布时间】:2013-10-03 02:47:36
【问题描述】:
假设我有很多现金,我想以 500 美元到 5,000 美元之间的随机增量发放。我希望范围的下限比更高的范围更有可能。我可以用 Ruby 编写以这种方式随机发放现金的最有效算法是什么?
【问题讨论】:
-
你能添加一些你尝试过的东西吗?您的问题目前要求其他 SO 用户也能有效地解决您的问题,而您无需付出明显的努力。
标签: ruby algorithm probability
假设我有很多现金,我想以 500 美元到 5,000 美元之间的随机增量发放。我希望范围的下限比更高的范围更有可能。我可以用 Ruby 编写以这种方式随机发放现金的最有效算法是什么?
【问题讨论】:
标签: ruby algorithm probability
我认为最简单的方法就是使用 case 语句:
def get_price
case rand(100) + 1
when 1..50 then 500
when 50..75 then 1000
when 75..99 then 2500
when 99..100 then 10000
end
end
p get_price # => 500
调用 get_price 将以 50% 的概率返回 500,但只有 2% 的时间返回 10000。
【讨论】:
一种方法是首先定义多个范围并为每个范围分配概率“权重”。这是一个例子:
weights = {[500, 1000] => 17,
[1001, 1500] => 15,
[1501, 2000] => 13,
[2001, 2500] => 12,
[2501, 3000] => 11,
[3001, 3500] => 10,
[3501, 4000] => 10,
[4001, 4500] => 10,
[4501, 5000] => 10}
在这里,权重为 15 的范围 [1001, 1500] 比权重为 10 的四个最高范围中的任何一个都高 50%。您可以有任意数量的范围和(如这里) 权重总和不必为 100。在这里,您可以将四个最高范围替换为单个范围 [3001, 5000] => 40。
我们的想法是使用您提供的权重随机选择一个范围,然后在该范围内选择一个随机值,其中该范围内的每个值都同样可能被选中。
ranges = weights.keys # => [[500, 1000], [1001, 1500],.., [4501, 5000]]
cum_wights = weights.values # => [17, 15,.., 10]
(1..weights.size-1).each {|i| cum_weights[i] += cum_weights[i-1]}
# cum_weights => [17, 32,.., 108]
# Obtain range randomly
rn = rand(cum_weights) # => random number between 0 and cum_weights.last (here 108)
i = 0 # range index
i += 1 while cum_weights[i] <= rn
rr = ranges[i] # random range
# Obtain uniform random value in range rr
# Obtain uniform random value in range i
# Since `rn` is equally-likely for any value in `rr`,
cwt_min, cwt_max = (i > 0 ? cum_weights[i-1] + 1 : 0), cum_weights[i]
random_amount = rr.first + ((rn - cwt_min).to_f/(cwt_max - cwt_min + 1)) * (rr.last-rr.first + 1)
或者干脆生成另一个随机数:
random_amount = rr.first + rand(rr.last-rr.first)
顺便说一句,我在赠送随机金额方面非常有经验。如果我能提供帮助,请告诉我。
【讨论】:
a=.7, b=2: en.wikipedia.org/wiki/Beta-binomial_distribution n+1 是箱子的数量,你可以通过计算pmf(显示在图表下方)。
听起来您想生成具有向左(或向右,我永远无法保持笔直;驼峰在左侧)分布的高斯(又名正态)分布的随机数。
这里是采样偏态正态分布算法的 VBA 实现(警告:弹出窗口):http://www.ozgrid.com/forum/showthread.php?t=108175
把它翻译成 ruby 应该不难。
【讨论】: