Leo*_*Leo 39 java random non-uniform-distribution
如何n
在Java中创建一个随机整数,在"线性递减分布" 之间1
和之间k
,即1
最有可能,2
不太可能,3
不太可能,......,k
最不可能,并且概率线性下降,如下所示:
我知道已经有关于这个主题的线程,我为制作一个新主题道歉,但我似乎无法从他们那里创造我需要的东西.我知道使用import java.util.*;
代码
Random r=new Random();
int n=r.nextInt(k)+1;
Run Code Online (Sandbox Code Playgroud)
在1
and 之间创建一个随机整数k
,均匀分布.
GENERALIZATION:任何提示创建任意分布的整数,即f(n)=some function
,P(n)=f(n)/(f(1)+...+f(k))
),也将受到赞赏,例如:
.
Bri*_*y37 18
这应该给你你需要的东西:
public static int getLinnearRandomNumber(int maxSize){
//Get a linearly multiplied random number
int randomMultiplier = maxSize * (maxSize + 1) / 2;
Random r=new Random();
int randomInt = r.nextInt(randomMultiplier);
//Linearly iterate through the possible values to find the correct one
int linearRandomNumber = 0;
for(int i=maxSize; randomInt >= 0; i--){
randomInt -= i;
linearRandomNumber++;
}
return linearRandomNumber;
}
Run Code Online (Sandbox Code Playgroud)
此外,这是从开始索引到stopIndex的范围内POSITIVE函数(负函数实际上没有意义)的一般解决方案:
public static int getYourPositiveFunctionRandomNumber(int startIndex, int stopIndex) {
//Generate a random number whose value ranges from 0.0 to the sum of the values of yourFunction for all the possible integer return values from startIndex to stopIndex.
double randomMultiplier = 0;
for (int i = startIndex; i <= stopIndex; i++) {
randomMultiplier += yourFunction(i);//yourFunction(startIndex) + yourFunction(startIndex + 1) + .. yourFunction(stopIndex -1) + yourFunction(stopIndex)
}
Random r = new Random();
double randomDouble = r.nextDouble() * randomMultiplier;
//For each possible integer return value, subtract yourFunction value for that possible return value till you get below 0. Once you get below 0, return the current value.
int yourFunctionRandomNumber = startIndex;
randomDouble = randomDouble - yourFunction(yourFunctionRandomNumber);
while (randomDouble >= 0) {
yourFunctionRandomNumber++;
randomDouble = randomDouble - yourFunction(yourFunctionRandomNumber);
}
return yourFunctionRandomNumber;
}
Run Code Online (Sandbox Code Playgroud)
注意:对于可能返回负值的函数,一种方法可以是获取该函数的绝对值,并将其应用于每个yourFunction调用的上述解决方案.
所以我们需要以下分布,最不可能的是:
*
**
***
****
*****
Run Code Online (Sandbox Code Playgroud)
等等
让我们尝试将均匀分布的整数随机变量映射到该分布:
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
Run Code Online (Sandbox Code Playgroud)
等等
这样,如果我们生成一个均匀分布的随机整数,从1到15,在这种情况下为15 K = 5
,我们只需要找出它适合它的桶.棘手的部分是如何做到这一点.
请注意,右边的数字是三角形数字!这意味着,对于随机生成的X
,从1
到T_n
,我们只需要找到N
这样T_(n-1) < X <= T_n
.幸运的是,有一个明确定义的公式可以找到给定数字的"三角形根",我们可以将其用作从均匀分布到存储区的映射的核心:
// Assume k is given, via parameter or otherwise
int k;
// Assume also that r has already been initialized as a valid Random instance
Random r = new Random();
// First, generate a number from 1 to T_k
int triangularK = k * (k + 1) / 2;
int x = r.nextInt(triangularK) + 1;
// Next, figure out which bucket x fits into, bounded by
// triangular numbers by taking the triangular root
// We're dealing strictly with positive integers, so we can
// safely ignore the - part of the +/- in the triangular root equation
double triangularRoot = (Math.sqrt(8 * x + 1) - 1) / 2;
int bucket = (int) Math.ceil(triangularRoot);
// Buckets start at 1 as the least likely; we want k to be the least likely
int n = k - bucket + 1;
Run Code Online (Sandbox Code Playgroud)
n
现在应该具有指定的分布.
有很多方法可以做到这一点,但可能是最简单就是生成
2个随机整数,一个之间0
和k
,称它为x
之间一个0
和h
,把它y
.如果y > mx + b
(m
并b
适当选择......)那么
k-x
,否则x
.
编辑:回复此处的评论,以便我可以有更多的空间.
基本上我的解决方案利用原始分布中的对称性,其中p(x)
是线性函数x
.我在编辑之前回复了关于泛化的问题,并且这个解决方案在一般情况下不起作用(因为在一般情况下没有这种对称性).
我想象这样的问题:
k x h
都有一个共同的斜边.复合形状是k x h
矩形.你也必须照顾边缘情况(我没有打扰).例如,我现在看到你的发行从1开始,而不是0,所以那里有一个一个一个,但它很容易修复.