模拟加权随机数 - Java

时间:2015-02-22 16:43:17

标签: java random probability

我查看了多个堆栈溢出文章,但无法找到合理的响应。如果有重复请注明。

我有一个项目列表。类似的东西:

String giantRat []={"Bandage", "Healing Potion", "Minor Healing Potion", "Rat Teeth", "Fur", "Rat Tail", ""};

这表示此giantRat可能丢失的项目。

有一个具有匹配索引的相关数组,它保存了我希望的出现加权概率。类似的东西:

int giantRatDropRate[]={1,1,1,6,8,3,5};

这些将按比例放大50,(每个乘以2),然后理论上我将扮演一个50面骰子(Random)。这似乎是错误的方法,我无法找到一种方法来做到这一点。

同样,我们的想法是掷骰子并根据加权从列表中选择1项。也许掷骰子是错误的方式。任何帮助表示赞赏。

5 个答案:

答案 0 :(得分:2)

使用Random.nextInt(n),其中n是权重的总和;然后,根据结果int下降的间隔,确定项目;例如如果是0 - 取第1项;如果介于3和8之间(包括) - 采取第四项。

您可以轻松地将权重数组转换为区间边界数组:只需对所有前面的元素求和。 然后,使用random int,只需遍历此区间边界数组,并在随机int变得大于数组的当前元素时停止。

因为间隔的长度由权重决定,所以概率也由它确定。

答案 1 :(得分:1)

只需计算每个元素所具有的值的间隔。让我们忘记乘以2而不带任何东西。

第一个元素的权重为1,因此其间隔为[0, 1[

第二个的权重为1,所以让我们以前一个的值开始其间隔,并添加1:[1, 2[

第三个相同:[2, 3[

第4个的权重为6,因此其间隔为[3, 9[

继续直到结束。

然后滚动你的骰子,找到一个间隔覆盖骰子值的元素。

答案 2 :(得分:1)

一种简单的方法可以如下。不需要* 2,因为概率是相同的。

    String giantRat []={"Bandage", "Healing Potion", "Minor Healing Potion", "Rat Teeth", "Fur", "Rat Tail", ""};


    int[] a = {1,1,1,6,8,3,5};
    int sum = 0;
    for(int i: a)
       sum += i;
    Random r = new Random();
    int s = r.nextInt(sum);  //Get selection position (not array index)

    //Find position in the array:
    int prev_value = 0;
    int current_max_value = 0;
    int found_index = -1;
    for(int i=0; i< a.length; i++){ //walk through the array
      current_max_value = prev_value + a[i];
      //is between beginning and end of this array index?
      boolean found = (s >= prev_value && s < current_max_value)? true : false;
      if( found ){
        found_index = i;
        break;
      }
      prev_value = current_max_value;
    }

    String selection = "unknown";
    if( found_index != -1 ){
      selection = giantRat[found_index];
    }
    System.out.println(selection);

http://ideone.com/xyQlvN

的示例

答案 3 :(得分:0)

您可以这样做的一种方法是将每个索引存储在大小为50的数组中。所以:

 int[] giantRatDropRate = new int[50];
 giantRatDropRat = { 0 , 0 , 1 , 1 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3... };

然后,如果您愿意,可以随机随机播放阵列,请参阅Random shuffling of an array

最后,使用随机数生成器从该数组中获取索引:      double d = 50.0 * Math.random();      String action = giantRat [giantRatDrop [(int)d]];

答案 4 :(得分:0)

好消息:我在评论部分采用了@pds建议的非严厉方法,并提出了我自己的解决方案。我认为答案部分的@pds解决方案是一个更有说服力的解决方案,但在研究他并稍微考虑我的问题之后,这是我自己的看法:

https://gist.github.com/anonymous/f985c1839e5a6be94883