在java中,当我想生成一个高斯值时,我直接使用
Random r = new Random();
r.nextGaussian();
但现在我想生成一个概率为 1/x 的值,而不是高斯!
在我的解决方案中,我必须创建一个随机值,但这些值以越接近 1 开始,依此类推(有序)。例子 :
0.98
0.90
0.85
0.6
0.4
...
并不是
0.3
0.9
0.4
0.8
...
我们有关于 java 的解决方案吗?
要找到以 为概率分布的值1/x
:
1/x
is的积分ln x
,正如@dbaupp 指出的那样,它无限增长。事实上,ln x
当 x 接近 0 时,极限是无限的(负),而当它增长到正无穷时,极限是无限的(正)。
所以我们必须将函数的范围限制在某个区间[min, max)
,其中min > 0
和 都是有限的。
的倒数q = ln x
是x = e^q
,所以分位数函数是e^[(ln max - ln min)q + ln(min)]
,其中 q 落在区间内[0,1)
经过一点代数,就变成了(max/min)^q * min
=(max^q)(min^(1-q))
(我不确定哪种形式在数值上更稳定)
因此,将范围从 0 到 1 的均匀分布值(例如您从 nextDouble 获得的值)插入此函数将为您提供具有 apdf = 1/x
且范围从给定最小值到最大值的值:
public static double reciprocalQuantile(double q, double min, double max) {
return Math.pow(max, q)*Math.pow(min, 1-q);
}
所以你可以说:
Random rand = new Random();
double value = reciprocalQuantile(rand.nextDouble(), 0.0001, 10000);
我认为:-)请随时检查我的数学。
还有一点:您当然可以将 min 设置为 Double.MIN_VALUE 并将 max 设置为 Double.MAX_VALUE,但我对浮点表示的了解不够多,无法知道这是否会出现问题,如果是,那么我不知道一个数字需要多小/多才能变得如此。它也可能不是很有用。一个小测试显示了很多非常小的值和很多非常大的值——这并不奇怪,因为顶部和底部的积分接近无穷大。因此,要在中等范围内获得足够的值以获得漂亮的直方图,您需要很多值。
您可能需要实现自己的转换方法。从 Random 实例中,您可以获得用于以均匀概率获取数字的对象,并将这些作为输入到您的方法中,以将其转换为您喜欢的任何分布。因此,您将获取生成的数字,并将其用于计算 1/x(不确定您的意思是什么......)并根据需要返回该操作的结果......
Random random = new SecureRandom();
double x = random.nextDouble();
return 1.0 / x;
将为您在范围 [0.0, 1.0] 内为 x 提供值 1/x
编辑 - 不回答 OP 的问题,我误解了。