当你在大多数编程语言中使用random(min,max)函数时,它的分布是怎样的?
如果我想要产生20%时间内的一组数字和80%时间内的另一组数字,我该如何生成符合这种要求的随机数序列呢?
例如:我应该获得随机频率,但是“1”的频率必须比“0”的频率高约20%。
当你在大多数编程语言中使用random(min,max)函数时,它的分布是怎样的?
如果我想要产生20%时间内的一组数字和80%时间内的另一组数字,我该如何生成符合这种要求的随机数序列呢?
例如:我应该获得随机频率,但是“1”的频率必须比“0”的频率高约20%。
就像任何人所说的那样,大多数语言中的伪随机数生成器实现了(0,1)上的均匀分布。 如果你有两个响应类别(0,1),其中1的概率为p,那么你将得到一项伯努利分布,可以用以下方法来模拟
# returns 1 with p probability and 0 with (1-p) probability
def bernoulli(p)
rand()<p ? 1:0;
end
就是这么简单。 偏态正态分布是一种完全不同的东西,由正态分布的概率密度函数和累积分布函数“联合”而成,以此来创造偏斜。你可以在Azzalini的作品这里中阅读相关内容。使用gem分布,您可以生成概率密度函数,其中
# require 'distribution'
def sn_pdf(x,alpha)
sp = 2*Distribution::Normal.pdf(x)*Distribution::Normal.cdf(x*alpha)
end
获取累积分布函数很困难,因为没有解析解,所以您需要进行积分。 要从偏斜正态分布中获取随机数,可以使用接受-拒绝算法。
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%。
这是一种可能的方法:
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
If (RandomNumber) < 200 // 20%
RandomVariable = 0
Else // 80%
RandomVariable = 1
这个逻辑当然可以应用于n个离散变量。
你的问题与示例有很大不同。因此,我将回答两个问题,你可以找出哪个是你真正想要的答案。
1)你的示例(我不知道Ruby或Java,所以请容忍我)
2)生成带偏斜的正态分布的随机数
如何呢
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);
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