Java中的离散概率分布

Java中的离散概率分布,java,math,probability,Java,Math,Probability,我有一组整数,每个整数都分配了一个概率,从早期的实验中得出,例如: 0 = 0.5 1 = 0.2 2 = 0.3 根据概率分布的规范,这些权重总和为1.0。 我现在正在寻找一种有效的方法,在考虑给定概率的同时对其中一个值进行采样,例如(伪码): 根据给定的数字,这将导致0一半的时间。但是,不要假设这些之间存在任何模式或规律 我在以前的实验中一直使用它,但它似乎没有为这个场景提供解决方案,也没有 我不知道这是否是因为我错过了一个简单的解决方案。一个简单的实现似乎或多或少是直截了当的,但要有效地

我有一组整数,每个整数都分配了一个概率,从早期的实验中得出,例如:

0 = 0.5
1 = 0.2
2 = 0.3
根据概率分布的规范,这些权重总和为1.0。 我现在正在寻找一种有效的方法,在考虑给定概率的同时对其中一个值进行采样,例如(伪码):

根据给定的数字,这将导致0一半的时间。但是,不要假设这些之间存在任何模式或规律

我在以前的实验中一直使用它,但它似乎没有为这个场景提供解决方案,也没有


我不知道这是否是因为我错过了一个简单的解决方案。一个简单的实现似乎或多或少是直截了当的,但要有效地实现这一点需要相当多的时间。这就是为什么我要寻找一个已建立的实现。

考虑到分位数函数的简单性和手动实现的琐碎性,我认为明确写出这一点没有任何害处

在[0,1]中绘制随机数
r
后,使用


if(r一个非常简单的通用解决方案是:

class Distribution<T>{
    List<Double> probs = new ArrayList<>();
    List<T> events = new ArrayList<>();
    double sumProb;
    Random rand = new Random();

    Distribution(Map<T,Double> probs){
        for(T event : probs.keySet()){
            sumProb += probs.get(event);
            events.add(event);
            this.probs.add(probs.get(event));
        }
    }

    public T sample(){
        T value;
        double prob = rand.nextDouble()*sumProb;
        int i;
        for(i=0; prob>0; i++){
            prob-= probs.get(i);
        }
        return events.get(i-1);
    }
}
类分布{
List probs=new ArrayList();
列表事件=新建ArrayList();
双苏姆普罗;
Random rand=新的Random();
分布(地图问题){
对于(T事件:probs.keySet()){
sumProb+=probs.get(事件);
事件。添加(事件);
this.probs.add(probs.get(event));
}
}
公共T样本(){
T值;
double prob=rand.nextDouble()*sumProb;
int i;
对于(i=0;prob>0;i++){
prob-=probs.get(i);
}
返回事件。get(i-1);
}
}

您可以根据需要随意更改它,例如添加其他构造函数。当然,这里有很多东西需要改进,从效率开始,但以后可以大量重用。

调用
Random.nextDouble()
是一个相当昂贵的操作。您最好使用
Random.nextInt(n)
在这种情况下

int num = rand.nextInt(10);
return num <= 5 ? 0 : num <= 8 ? 1 : 2;
int num=rand.nextInt(10);

return num如果(Math.rand()>0.5){//result is 0}这样的小事你能逃脱吗?这被称为离散分布。有一些关于“有效地做这件事相当复杂”的好背景。以什么方式?什么类型效率/你在寻求什么?@ErickG.Hagstrom我担心的复杂性是,这可能真的涉及到高维数据结构。我知道这是一个离散分布,但我一直在寻找一个具体的实现。同时,我发现Apache Commons Math实际上似乎提供了一个名为
EnumeratedDistribution
/
EnumeratedIntegerDistribution
。因为您找到了“已建立的实现”你的问题要求,提供你自己的答案不是很有意义吗?在我看来,这将是最明智/最有用的事情。尽管最终在Apache Commons数学中遇到了
EnumeratedIntegraterDistribution
,但我认为这提供了最完整的解决方案,谢谢!谢谢你的提示,我认为不是他的答案可能很有价值。但是,这应该是对其他解决方案的评论,不是吗?@Carsten他实际上提供了一个完整的解决方案。这是一个非常简洁的答案,但它是一个答案,它很简单,很有效,而且表现很好。是的,不幸的是,我只能将一个答案标记为正确。@ctst的答案似乎更一般,这是正确的为什么我选了他的一个。@Carsten请随意投票。即使你们不能决定,我也会奖励代表分数最低的人;)
class Distribution<T>{
    List<Double> probs = new ArrayList<>();
    List<T> events = new ArrayList<>();
    double sumProb;
    Random rand = new Random();

    Distribution(Map<T,Double> probs){
        for(T event : probs.keySet()){
            sumProb += probs.get(event);
            events.add(event);
            this.probs.add(probs.get(event));
        }
    }

    public T sample(){
        T value;
        double prob = rand.nextDouble()*sumProb;
        int i;
        for(i=0; prob>0; i++){
            prob-= probs.get(i);
        }
        return events.get(i-1);
    }
}
int num = rand.nextInt(10);
return num <= 5 ? 0 : num <= 8 ? 1 : 2;