当你在大多数语言中使用随机(最小,最大)函数时,分布是什么样的?
如果我想在20%的时间内生成一系列数字,并且在80%的时间内生成另一个数字范围,我该如何生成随后的一系列随机数呢?
ex)我应该得到随机频率,但“1”的频率必须比频率“0”高出约20%
答案 0 :(得分:1)
大多数伪随机生成器内置编程语言产生 均匀分布 ,即该范围内的每个值与生成的任何其他值具有相同的概率。范围。实际上,在某些情况下,这一要求是语言标准的一部分。某些语言(如Python或R)支持各种常见发行版。
如果语言不支持,您必须使用数学技巧来制作其他发行版,例如来自统一发行版的正态发布,或者您可以查找执行此功能的第三方库。
你的问题似乎要简单得多,因为随机变量是离散 (及其更简单的类型,即二进制)。这些技巧的诀窍是在给定范围内产生一个均匀分布的随机数,比如0到999,并按照与每个值相关的比例分割这个范围,在这种情况下,这将是: / p>
If (RandomNumber) < 200 // 20%
RandomVariable = 0
Else // 80%
RandomVariable = 1
这个逻辑当然可以应用于n个离散变量。
答案 1 :(得分:1)
对于大多数语言,生成的随机数可能取决于该语言中的算法,也可能是基于时间,处理器,种子数等几个因素随机生成的。
分布不正常。事实上,如果函数返回5个整数,则所有5个整数都很有可能出现在下一个函数调用中。这也称为统一分布。
所以说如果你希望在20%的时间内产生一个数字(比如7),而在80%的时间内产生另一个数字(比如13),你可以这样做一个数组:
var arr = [7,13,13,13,13];
var picked = arr[Math.floor(Math.random()*arr.length)] ;
// since Math.random() returns a float from 0.0 to 1.0
因此,7有20%的机会出现,13有80%的机会。
答案 2 :(得分:1)
这是一种可能的方法:
ranges = [(10..15), (20..30)]
selector = [0, 0, 1,1,1,1,1,1,1,1] # 80:20 distribution array
# now select a range randomly
random_within_range(ranges(selector[random(10)]))
def random_within_range range
rand (range.last - range.begin - (range.exclude_end? ? 1 : 0)) + range.begin
end
答案 3 :(得分:1)
您的问题与您的示例有很大不同。所以我会回答这两个问题,你可以找出你真正想要的答案。
1)你的例子(我不知道ruby或java,所以忍受我)
2)从具有偏斜的正态分布生成随机数
答案 4 :(得分:1)
就像任何人说的那样,大多数语言中的伪随机数生成器实现了(0,1)上的均匀分布。 如果你有两个响应类别(0,1),p概率为1,你有一个伯努利分布,可以用
模拟# returns 1 with p probability and 0 with (1-p) probability
def bernoulli(p)
rand()<p ? 1:0;
end
这很简单。 倾斜的正态分布是完全不同的野兽,由正常分布的pdf和cdf的'联合'产生,以产生偏斜。你可以阅读Azzalini的作品here。使用gem分布,您可以使用
生成概率密度函数# require 'distribution'
def sn_pdf(x,alpha)
sp = 2*Distribution::Normal.pdf(x)*Distribution::Normal.cdf(x*alpha)
end
获得cdf很困难,因为没有分析解决方案,所以你应该整合。 要从偏斜法线中获取随机数,可以使用acceptation-rejection算法。
答案 5 :(得分:0)
大多数计算机语言对其(伪)随机整数生成器均匀分布。所以每个整数都有可能。
对于您的示例,假设您想要“1”55%的时间和“0”45%的时间。
要使这些频率不相等,请尝试生成1到100之间的随机数。如果生成的数字是1到55,则输出“1”;否则输出“0”。
答案 6 :(得分:0)
怎么样
var oneFreq = 80.0/100.0;
var output = 0;
if (Math.random() > oneFreq)
output = 1;
或者,如果您希望20%的值介于0和100之间,80%介于100和200之间。
var oneFreq = 80.0/100.0;
var oneRange = 100;
var zeroRange = 100;
var output = Math.random();
if (output > oneFreq)
output = zeroRange + Math.floor(oneRange * (output - oneFreq));
else
output = Math.floor(zeroRange * output);
答案 7 :(得分:0)
在红宝石中,我会这样做:
class DistributedRandom
def initialize(left, right = nil)
if right
@distribution = [0] * left + [1] * right
else
@distribution = left
end
end
def get
@distribution[rand @distribution.length]
end
end
使用80:20分发运行测试:
test = [0,0]
rnd = DistributedRandom.new 80, 20 # 80:20 distribution
10000.times { test[rnd.get] += 1 }; puts "Test 1", test
在右侧运行20%以上分布的测试:
test = [0,0]
rnd = DistributedRandom.new 100, 120 # +20% distribution
10000.times { test[rnd.get] += 1 }; puts "Test 2", test
使用具有超过91个离散值的三角函数的自定义分布运行测试,但输出不适合以前的测试:
test = [0,0]
rnd = DistributedRandom.new((0..90).map {|x| Math.sin(Math::PI * x / 180.0)})
10000.times { test[rnd.get] += 1 }; puts "Test 3", test
答案 8 :(得分:-1)
如果您想要一个良好的数学理解,请查看this lecture。