我正在尝试制作一个使用Monte Carlo Hit或Miss Simulation的随机发生器。
我有一个Key-Value对,代表ID和概率值:
ID - Value
2 - 0.37
1 - 0.35
4 - 0.14
3 - 0.12
当您添加所有这些值时,您将获得总计1.0。
您可以将这些值想象为“车轮”上“切片”的总面积(EG:ID 2占车轮的37%,而ID 3仅占车轮的12%)。当转换为“范围”时,它将如下所示:
ID - Value - Range
2 - 0.37 - 0 to 37
1 - 0.35 - 37 to 72
4 - 0.14 - 72 to 86
3 - 0.12- 86 to 100
现在,我使用Random.NextDouble()生成一个介于0.0和1.0之间的随机值。该随机值将被视为车轮上的“旋转”。比方说,随机数发生器返回0.35,然后选择ID 2。
鉴于我有一系列双打,实现这个的最佳方法是什么?
答案 0 :(得分:4)
最简单的解决方案通常是最好的,如果您的范围是0到100(或者另一个可管理的小编号),您可以分配int[]
并使用您创建的范围表填写ID在相应的索引处,您的“throw”将如下所示:
int randomID = rangesToIDs[random.nextInt(rangesToIDs.length)];
顺便说一下,没有必要对范围大小的ID进行排序,因为假设randoms是均匀分布的,在查找表中放置范围的位置无关紧要。唯一重要的是条目数量与投掷ID的机会成正比。
答案 1 :(得分:1)
假设您的初始数据表示为数组D [n],其中D [i] =(id,p)和sum(D [i] .p,i = 0..n-1)== 1
构建第二个数组P [n],使得P [i] =(q,id):P [i] =(sum(D [j] .p,j为0..i),D [j ] .id) - 即,将每个切片i的个体概率转换为i(包括)之前的所有切片的累积概率。注意,根据定义,该数组P按字段q排序(即按累积概率)。
现在您可以使用binary search查找随机数r选择的切片(0 <= r&lt; = 1):
找到最高的i,使得P [i] .q <= r;那么P [i] .id就是你的切片。
通过使用固定网格散列概率范围,可以进一步加快查找速度。如果有人有兴趣,我可以写一些关于这方面的更多细节。
答案 2 :(得分:0)
一个有序的地图/字典,其中'Value'作为键,'ID'作为值,可以让你快速找到你所在范围的上限,然后查找该范围的ID
假设你的字典允许它,二元搜索最好找到上限而不是整个字典中的内容
答案 3 :(得分:0)
由于jk写的排序字典应该没问题。
假设你有这样的词典:
0.37 2
0.72 1
0.86 4
1.00 3
你滚动xx = 0.66 .. 从最低编号(即0.37)开始迭代字典 如果xx&lt;字典[I]的.key return dict [i] .value
或者我想到的另一个解决方案是包含下限和上限以及值的自定义对象列表。然后遍历列表并检查滚动数是否在上限和下限范围内。
答案 4 :(得分:0)
boundaries = [37, 72, 86, 100]
num = 100 * random
for i in boundaries:
if num < i then return i