在java中,当我想生成高斯值时,我直接使用
Random r = new Random();
r.nextGaussian();
但现在我想生成一个具有 1/x 概率的值,而不是高斯!
在我的解决方案中,我必须创建一个随机值,但这些值从更接近 1 的值开始,依此类推(orderred)。 示例:
0.98
0.90
0.85
0.6
0.4
...
而不是
0.3
0.9
0.4
0.8
...
我们有 Java 解决方案吗?
最佳答案
要查找以 1/x
概率分布的值:
1/x
的积分是 ln x
,正如 @dbaupp 所指出的,它的增长没有界限。事实上,当 x 接近 0 时,ln x
的极限是无限(负),当它增长到正无穷大时,极限是无限(正)。
因此,我们必须将函数的范围限制在某个区间 [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 获得的值)插入此函数将为您提供 pdf = 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,但我对浮点表示了解不够,不知道这是否会出现问题,如果是,那么我不知道不知道需要多小/多大的数字才能变成这样。它也可能不是很有用。一些测试显示了许多非常小的值和许多非常大的值——这并不奇怪,因为顶部和底部的积分接近无穷大。因此,要在中等范围内获得足够的值以获得漂亮的直方图,您需要很多值。
关于java - 随机生成值 1/x,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10383771/