在Java中生成具有最大值、最小值和平均值的随机数

20

我需要生成具有以下属性的随机数:

最小值应为200

最大值应为20000

平均数(均值)为500。

可选:第75个百分位数为5000

它绝不是均匀分布,也不是高斯分布。我需要一些左偏斜度。


2
这实际上是一个令人愉快的数学问题。我认为它与识别一个函数有关,该函数在0-300上的积分与其在300-19800上的积分相匹配,但我不知道自己能否进一步推导! - Cephron
1
@Richard:更好的是:有足够的信息定义任意数量的分布!;-) - Joachim Sauer
1
@Chuck:我可以想到很多用途,这并不意味着是作业。它可能是作业,但也可能不是。 - Joachim Sauer
2
@Chuck:蒙特卡罗模拟某些行为,当进行测量时显示出这些属性。 - Joachim Sauer
1
不,这不是一份作业。我正在开发一个原型,需要对这种分布进行建模。更多信息请参见:https://wiki.mozilla.org/Socorro:ClientAPI - Fuad Malikov
显示剩余10条评论
5个回答

12

由于Java Random只提供正态(高斯)分布,因此它可能不适用于您的需求。

您可能正在寻找的是f分布(请参阅下文)。您可以使用distlib库这里并选择f分布。您可以使用随机方法来获取您的随机数。

输入图像描述


1
F分布没有上下界,因此您必须将其截断以适应要求 - 这会使参数的计算变得复杂。 - leonbloy
@Scott 逆元并不总是容易获得的。在某些情况下,它们是不可能的。事实上,在任何非一对一函数中,都没有逆元(好吧,有多个有条件的逆元,定义在某些范围内)。任何这样的分布都没有直接的逆元。 - Ryan Amos
@Ryan,我的观点是有很多库(例如我提到的那个)可以帮你找到一个随机点。我不是说你应该自己写代码。它们是否使用查找表是你可以查看源代码的内容。我的意思只是说,有许多库可用,因此在大多数情况下不必编写自己的代码。 - Scott
@Scott 虽然那可能是真的,但那有什么乐趣呢? :P - Ryan Amos
就算价值不高,对于许多发行版而言,比起求逆 CDF,有更有效率的算法。其中最受欢迎的是信封拒绝法,@Scott 似乎在他的飞镖投掷类比中提到了这一点。该方法需要评估 PDF 并从信封分布生成随机数,通常更加高效。请参见 维基百科我的这一系列 4 篇博客文章 - Erik P.
显示剩余7条评论

9
假设 X 是您的目标变量,通过执行 Y=(X-200)/(20000-200) 来归一化范围。 现在您需要一些随机变量 Y,它的值在区间 [0,1] 中,并且其平均值为 (500-200)/(20000-200)=1/66
您有很多选择,其中最自然的一个似乎是 Beta分布Y ~ Beta(a,b)a/(a+b) = 1/66 - 您有一个额外的自由度,可以选择是否满足最后四分之一的要求。
之后,您只需将 X 返回为 Y*(20000-200)+200 要生成 Beta 随机变量,您可以使用 Apache Commons 或参见此处

4

这可能不是你想要的答案,但针对三个均匀分布的特殊情况:

均匀分布 (忽略左侧的数字,但它是按比例缩放的!)

public int generate() {
  if(random(0, 65) == 0) {
    // 50-100 percentile

    if(random(1, 13) > 3) {
      // 50-75 percentile
      return random(500, 5000);
    } else {
      // 75-100 percentile
      return random(5000, 20000);
    }

  } else {
    // 0-50 percentile
    return random(200, 500);
  }
}

如何得到这些数字

首先,曲线下的面积在200-500和500-20000之间是相等的。这意味着高度关系为300 * 左高度 == 19500 * 右高度,因此左高度 == 65 * 右高度

这给了我们1/66的机会选择正确的,以及65/66的机会选择左边。

然后我按照同样的方法计算第75个百分位数,但比率为500-5000 的机会 == 5000-20000 的机会 * 10 / 3。同样,这意味着我们有10/13的机会处于50-75百分位数区间,以及3/13的机会处于75-100百分位数区间。

致敬@Stas - 我正在使用他的“包含随机”函数。

是的,我意识到我的数字是错误的,因为这种方法是适用于离散数字,并且我的计算是连续的。希望有人能够纠正我的边界情况。


3
您可以拥有一个在[0;1]上工作的函数f,例如:
Integral(f(x)dx) on [0;1] = 500
f(0) = 200
f(0.75) = 5000
f(1) = 20000

I guess a function of the form

f(x) = a*exp(x) + b*x + c

这可能是一个解决方案,你只需要解决相关系统。

然后,你执行f(uniform_random(0,1)),就可以了!


0

由于存在许多具有给定最小值、最大值和平均值的随机分布,因此您的问题比较模糊。

实际上,众多解决方案之一是选择max的概率为(mean-min)/(max-min),否则选择min。也就是说,该解决方案仅生成最小值和最大值中的一个数字。

以下是另一种解决方案。

PERT分布(或beta-PERT分布)旨在采用最小值、最大值和估计模式。它是三角形分布的“平滑”版本,可以按以下方式实现从该分布生成随机变量:

startpt + (endpt - startpt) * 
     BetaDist(1.0 + (midpt - startpt) * shape / (endpt - startpt), 
          1.0 + (endpt - midpt) * shape / (endpt - startpt))

在编程中——

  • startpt 是最小值,
  • midpt 是众数(不一定是平均数或者均值),
  • endpt 是最大值,
  • shape 是一个大于等于0的数字,但通常为4,且
  • BetaDist(X, Y) 返回具有参数 XY 的beta分布的随机变量。

已知均值(mean),可以通过以下公式计算 midpt

3 * mean / 2 - (startpt + endpt) / 4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接