Java中有没有办法按照固定的平均值和标准差生成随机数?



问题

我知道如何生成具有固定平均值和标准差的随机数。

我还希望将这些值约束在一个范围内(我知道这意味着结果不会是真正的高斯分布,而是裁剪的高斯分布(

上下文

我试图回答的更广泛的问题是

假设你有一个黑匣子,每 10 秒发出一只猴子, 猴子的高度在 24 到 36 英寸之间。高度 生成超过半 n 小时的猴子遵循正态分布 平均值为 30.5 英寸,标准偏差为 2.5。虽然还有另一个 房间里的盒子,如果猴子的高度低于,就会消失 28 英寸,每 20 秒发生一次。编写要计算的程序 N 天后留在房间中的猴子数量(n 是用户 输入(。为了逻辑起见,假设空间足够大 容纳无限数量的猴子,它们有食物。

nextGaussian(( 方法返回平均值为 0、标准差为 1 的随机数。

这意味着 nextGaussian(( 返回的数字将倾向于在 0 附近"聚类",并且(大约(70% 的值将在 -1 到 1 之间。根据 nextGaussian(( 返回的值,您可以缩放和平移它们以获得其他正态分布:

  • 要更改分布的 maen(平均值(,请添加所需的 价值;

  • 要更改标准差,请将该值相乘。

例子: 要生成平均值为 500 且标准差为 100 的值,请执行以下操作:

double val = r.nextGaussian() * 100 + 500;

要生成平均值为 30.5 且标准差为 2.5 的值,请执行以下操作:

double val = r.nextGaussian() * 2.5 + 30.5;

有了这个 70% 的值将在 28 到 33 之间。由于99.7%的值位于3西格玛范围内,因此猴子的高度在24到36之间。

正如 VGR 在他们的评论中提到的,您可以使用 Random.nextGaussian(( 生成一个高斯分布随机数,平均值为零,标准差为 1。您可以通过添加此值来影响均值,并通过乘法影响标准差。因此,您可以一起生成具有被嘲笑的属性的随机数。你会想要

desiredMean + desiredStandardDeviation * Random.nextGaussian()

您已经陈述了一个额外的要求,即值必须在一个范围内,您只需重新滚动一个新值,直到获得该范围内的值,即可轻松实现此目的。

从JDK 17开始,Random和SecureRandom实现了接口RandomGenerator,该接口具有新的方法nextGaussian(double mean, double stddev)

OpenJDK实现与之前的答案相同:

default double nextGaussian(double mean, double stddev) {
if (stddev < 0.0) throw new IllegalArgumentException("standard deviation must be non-negative");
return mean + stddev * RandomSupport.computeNextGaussian(this);
}

最新更新