如何在Java方法中引入概率--以一种灵活而简洁的方式?

noj0wjuj  于 2023-01-07  发布在  Java
关注(0)|答案(2)|浏览(131)

我学习Java才一个半星期,目前为止,我能想到的在代码中加入随机性元素的唯一方法是使用 Random 类的 nextInt 方法,下面是我的方法的一部分:

Random random = new Random();
int randomInt = random.nextInt(10)+1;

[...]

if(randomInt <= 3){
System.out.println("Magnificent!");
} else if (randomInt >= 7){
System.out.println("Marvelous!");
} else {
System.out.println("Delectable!");
}

然而,它冗长且缺乏灵活性,我希望能够以简洁的方式将总概率为1的片段分配给不同的场景:事情A发生的概率是0.3,事情B发生的概率是0.5,事情С发生的概率是0.2,我怎么才能做到呢?

s5a0g9ez

s5a0g9ez1#

一般情况下,您有一组加权值,它可以基于概率产生一个随机值,该概率是其权重占总权重的分数。权重可以是归一化的(意味着它们的和为1),也可以是非归一化的,这是一个更容易的假设。
当从该集合中滚动随机值时,最有效的方法是首先检查概率最高的值。滚动0和总权重之间的随机数,然后按权重顺序(降序)遍历这些值,并检查随机数是否低于累积权重-〉如果是,则返回该值。
代码:

public class WeightedRandom<T> {    
    private final Comparator<WeightedValue<T>> byWeight = 
        Comparator.comparing(wv -> wv.weight);
    private final Set<WeightedValue<T>> weightedValues = 
        new TreeSet<>(byWeight.reversed());

    private double totalWeight;

    void put(double weight, T value) {
        if (weight <= 0) {
            return;
        }
        totalWeight += weight;
        weightedValues.add(new WeightedValue<>(weight, value));
    }

    public T next() {
        if (weightedValues.isEmpty()) {
            throw new NoSuchElementException();
        }
        double rnd = ThreadLocalRandom.current().nextDouble(totalWeight);
        double sum = 0;
        Iterator<WeightedValue<T>> iterator = weightedValues.iterator();
        WeightedValue<T> result;
        do {
            result = iterator.next();
            sum += result.weight;
        } while (rnd > sum && iterator.hasNext());
        return result.value;
    }

    private static class WeightedValue<T> {
        final double weight;
        final T value;

        public WeightedValue(double weight, T value) {
            this.weight = weight;
            this.value = value;
        }
    }
}

示例:

public static void main(String[] args) {
    WeightedRandom<String> random = new WeightedRandom<>();
    random.put(3, "AAA");
    random.put(2, "BBB");
    random.put(5, "CCC");

    for (int i = 0; i < 1000; i++) {
        String value = random.next();
        System.out.println(value);
    }
}
332nm8kg

332nm8kg2#

通常,你会使用Random.nextDouble(),测试random.nextDouble() < 0.3的概率为0.3。
为了检验一种以上的可能性,你需要把一些东西加起来,例如

double r = random.nextDouble();
if (r < 0.3) {
   ...0.3 probability
} else if (r < 0.8) {
   ...0.5 probability
} else {
   ...0.2 probability
}

相关问题