比方说,我得到了号码3
。然后我必须选择0到3之间的随机数,但是0的选择概率大于1,1选择的概率大于2,而2选择的概率大于3。 / p>
我已经知道,通过执行以下操作可以实现从0到3选择特定数字的百分比:
double r = Math.random();
int n = 0;
if (r < 0.5) {
n = 0;
// 50% chance of being 0
} else if (r < 0.8) {
n = 1;
// 30% chance of being 1
} else if (r < 0.95) {
n = 2;
// 15% chance of being 2
} else {
n = 3;
// 5% chance of being 3
}
问题是3
可以是任何东西。我怎么能这样做?
注意:数字0.5,0.8和0.95由我任意选择。我希望这些数字减少,以便所有这些数字的总和等于1,因此如果可能的话,它们都不相同。
答案 0 :(得分:6)
这似乎是您希望使用通用概率分布,其域可以根据您的喜好进行缩放。您可以选择f(0) = 0
和f(1) = 1
之类的任何功能。对于此示例,我将采用f(x) = x^2
。
要从此处获取随机数 - 更多值集中在0附近 - 我们可以执行以下操作:
numbers = ceil(max * f(rand()))
其中ceil
是天花板函数,max
是您想要的最高输出,f()
是您选择的函数,rand()
给出一个零之间的随机数一个。请注意,此函数的输出范围为1
到max
,而不是0
到max
。
下面的图表可以让您了解为什么这实际上有效:
请注意,当整数变大时,选择整数的可能性会减小 - 即ceil(max * f(x))等于“最长”1和“最短”10。
如果您希望所选数字与其数量之间存在直接关系,则只需选择不同的f(x)
即可。然而,在这一点上,这变成了一个数学问题而不是其他任何东西。我会寻找一个合适的f(x)
- 如果我理解你至少要找的东西并回复你。我猜到现在f(x)
将是e^x
,但我会仔细检查。
我希望这有帮助!
快速代码示例:
public int weightedRandom(int max, Random rand) {
return Math.ceil(((double) max) * Math.pow(rand.nextDouble(), 2));
}
我还在java程序中打印了一对,并在max == 10
:
2.0, 6.0, 8.0, 3.0, 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 7.0, 1.0, 4.0, 1.0, 1.0, 6.0, 8.0, 9.0, 7.0, 5.0
答案 1 :(得分:3)
我建议使用public double nextGaussian()
中的java.util.Random
方法
这允许在平均值
我再也不会解释它写在那里的内容Javamex nextGaussian(如果你想了解更多细节)
因此,实际上您需要0
和n
之间的值:
该方法将给出如下值:
偏差为1,无任何
Random r = new Random();
int n = 10;
int res = (int) Math.min(n, Math.abs(r.nextGaussian()) * n / 3);
所以:
n
:偏差变为n
n
)Math.abs
,因为它与中间Math.min
n
作为最终检查
测试10 000次迭代:
答案 2 :(得分:0)
您可以将函数应用于随机数,以减少出现数字接近1的机会。 然后乘以你的(无法到达的)最大数字:在这个例子中为4
{{1}}
答案 3 :(得分:0)
“均匀”可能意味着“每个连续数字的概率减少固定数量”或“每个连续数字减少固定百分比的概率”。例如,如果您使用50%的固定百分比随机选择4个数字:
如果你想每次减少一个随机(但递减)的百分比,你可以只生成一个小于前一概率的概率的随机数 - 即如果第一个的概率是0.5 ,第二个的概率是0.0 < p&lt; 0.5。但是,您可能希望比这更复杂一点,否则您可能会面临最后几个项目的微小百分比。例如,如果您为第二项随机选择0.1,则第三项的概率是0.0 <范围内的随机数。 p&lt; 0.1,这是非常小的,它只会从那里变得更糟。您可能希望使连续项的概率同时具有最小值和最大值(例如,第二项的概率为0.3
请注意,我使用<
而非<=
的事实非常非常重要。例如,您不希望0.0 <= p <= 0.5,因为这意味着第二项可能与第三项(您不想要的)具有相同的概率,并且它是所有后续项目的概率也可能等于0.0(即第一个数字的概率为100%,任何其他数字概率为0%,这根本不是你想要的)。
后一种策略的弱点在于你必须调整其中一个概率,使它们加起来为1.0。