如何可能得到一个具有特定概率的随机数



我想制作一个1-50000范围内的随机数选择器。

但我想这样做,使数字越大,概率越小。

概率,比如(1/2*数字(或其他什么。

有人能帮忙吗?

您需要某种类型的映射函数。从Random中得到的是一些"基元"构造,您可以信任这些构造,它们可以完全按照javadoc规范所说的那样执行:

  • .nextInt(X),它返回均匀随机(即概率图是一条精确的水平线(,一个在0和X-1之间随机选择的数字
  • .nextBoolean(),它给你1个随机性
  • .nextDouble(),给你一个介于0.0和1.0之间的几乎一致的随机数
  • nextGaussian(),它给你一个随机数,它的概率图是一条标准偏差为1.0、中点(平均值(为0.0的均匀正态曲线

对于双返回方法,如果想要精确的精度,就会遇到一些麻烦。电脑并不神奇。因此,如果你写这个映射函数,把nextDouble()变成一个标准的均匀分布的六面压模辊,你会认为:int dieRoll = 1 + (int) (rnd.nextDouble() * 6);可以做到。如果double是完美的,你就对了。但事实并非如此,因此,在最好的情况下,6个骰子面中有4个会出现750599937895083次,其他2个骰子面会出现7505.9937895082次。很难真正注意到这一点,但事实证明这是不完美的。我想这种微小的偏差对你来说并不重要,但是,只要你提到double,固有的微小错误就会蔓延到一切中,你真的无法阻止这种情况的发生。

您需要的是某种映射函数,它可以使用任意数量的此类随机提供的数据(来自这3个基元,如果您想避免double固有的错误,则实际上仅来自nextInt/nextBoolean(来生成您想要的数据。

例如,假设我给你的"原始"是一个介于1和6之间(包括1和6(的统一随机值,即:标准的6面压模辊。我要求您提出一个统一算法(如中所示,每个值的可能性都相等(,以产生2到12之间的数字,包括2和12。

也许你可能会想:简单,只需掷2个骰子并将其相加。但这是不正确的:7比12更有可能。

相反,你可以掷1个骰子,然后登记它是偶数还是奇数。然后你滚动第二个骰子,这就是你的结果,除非第一个骰子是奇数,在这种情况下你加6。如果你在第一个骰子上得到奇数,在第二个冲模上得到1,你就重新开始这个过程;最终你肯定不会翻白眼。

那将是均匀随机的。

你可以把同样的原则应用于你的问题。你需要一个数学函数,将.nextInt()的"水平线"映射到你想要的任何曲线。例如,听起来你可能想生成一些东西,然后取平方根并将其四舍五入。你必须画出或写一个公式,精确地描述概率密度。

这里有一个例子:

while (true) {
int v = (int) (50000.0 * Math.abs(r.nextGaussian()));
if (v >= 1 && v <= 50000) return v;
}

这会返回一个大致正态分布的值,1是最有可能的,50000是最不可能的。

一个简单的公式可以让你非常接近你想要的是

Random random = new Random();
int result = (int) Math.pow( 50001, random.nextDouble());

这将给出一个范围为1 - 50000的结果,其中每个结果的概率与1 / result大致成比例,这正是您所要求的。

它之所以有效,是因为result是该范围内的任何值n的概率是P( n <= 50001^x < n+1),其中x随机分布在[0,1)中。这是x落在log(n)log(n+1)之间的概率,其中日志的基数为50001。但该概率与log (1 + 1/n)成正比,非常接近1/n

最新更新