有权重的随机nextInt吗?

时间:2015-04-11 21:57:35

标签: java random

我使用随机类生成1到5之间的随机数,如myrandom.nextInt(6),它工作正常,但我想知道是否有办法给一个特定的数字一个权重来增加它是概率出现,让我们说而不是%20概率我希望数字“4”具有%40概率而其他数字1,2,3,5平均分享剩余的%60概率。有没有办法呢?

提前致谢。

3 个答案:

答案 0 :(得分:2)

我使用数组。 E.g。

int[] arr = {4, 4, 4, 5, 5, 6};
int a = arr[random.nextInt(arr.length)];

要获得更具动态性的解决方案,请尝试此操作。权重不必与任何特定值相加。

public static <T> T choice(Map<? extends T, Double> map) {
    if (map == null || map.size() == 0)
        throw new IllegalArgumentException();
    double sum = 0;
    for (double w : map.values()) {
        if (Double.compare(w, 0) <= 0 || Double.isInfinite(w) || Double.isNaN(w))
            throw new IllegalArgumentException();
        sum += w;
    }
    double rand = sum * Math.random();
    sum = 0;
    T t = null;
    for (Map.Entry<? extends T, Double> entry : map.entrySet()) {
        t = entry.getKey();
        if ((sum += entry.getValue()) >= rand)
            return t;
    }
    return t;
}

您可以随时根据需要轻松添加/删除/更改地图中的条目。以下是使用此方法的示例。

Map<Integer, Double> map = new HashMap<>();
map.put(1, 40.0);
map.put(2, 50.0);
map.put(3, 10.0);
for (int i = 0; i < 10; i++)
    System.out.println(choice(map));

答案 1 :(得分:1)

您必须生成更大范围的数字(例如从1到100)并使用范围返回您真正想要的数字。例如:(在伪代码中)

r = randint(1..100)
if (r >= 1 && r <= 20) // 20% chance
    return 1
else if (r >= 21 && r <= 60) // 40% chance
    return 2

答案 2 :(得分:1)

pbadcefp的回答可能是最简单的。既然你在评论中说明你需要它是动态的,那么这里是另一种方法。请注意,权重基本上指定数字在数组中出现的频率,以便从

中选择
public int weightedRandom( Random random, int max, Map<Integer, Integer> weights ) {
    int totalWeight = max;
    for( int weight : weights.values() ) {
        totalWeight += weight - 1;
    }

    int choice = random.nextInt( totalWeight );
    int current = 0;
    for( int i = 0; i < max; i++ ) {
        current += weights.containsKey( i ) ? weights.get( i ) : 1;
        if( choice < current ) {
            return i;
        }
    }

    throw new IllegalStateException();
}

使用示例:

Map<Integer, Integer> weights = new HashMap<>();
weights.put( 1, 0 ); // make choosing '1' impossible
weights.put( 4, 3 ); // '4' appears 3 times rather than once

int result = weightedRandom( new Random(), 5, weights );

基本上,这相当于pbadcefp在阵列{ 0, 2, 3, 4, 4, 4 }上应用的解决方案

如果要使用百分比,则必须对此进行调整。只需相应地计算权重。另外,我没有对此测试角落,所以你可能想要更广泛地测试它。

这绝不是一个完整的解决方案,但我更愿意提供一些完整的解决方案,因为你应该自己做一些工作。

我也会记录并说恕我直言,这是过度设计;但你想要这样的东西。