Java 底重随机数

Java 底重随机数,java,Java,现在,我正在为一个小型游戏制作一个物品放置台 在这个游戏中,我希望你比其他人更容易收到某些物品,有些物品被选中的几率非常低 我尝试过使用以下内容: Random rand = new Random(); int chance = rand.nextInt(100) + 1; if(chance > 2){ //give common item; } else if(chance == 1){ //give rare item } 但是,当您在50多个项目的范围内执行此

现在,我正在为一个小型游戏制作一个物品放置台

在这个游戏中,我希望你比其他人更容易收到某些物品,有些物品被选中的几率非常低

我尝试过使用以下内容:

Random rand = new Random();
int chance = rand.nextInt(100) + 1;
if(chance > 2){
     //give common item;
}
else if(chance == 1){
     //give rare item
}
但是,当您在50多个项目的范围内执行此操作时,创建、修改以及执行代码都会变得非常繁琐


那么,是否存在某种底部重随机性,它会产生大量的低数字(1、2等)和很少的高数字(50、60等)?

使用
random.nextDouble()
在[0,1]中生成一个数字,然后你可以使用
Math.pow()
给它一个非线性偏差,并将其放大以覆盖你的范围,例如:

 int randomBiased (int max, float bias) {
     float v = Math.pow(random.nextDouble(), bias); 
     return (int)(v * max);
 }
或者,如果您更喜欢单衬里:

 int value = (int)(100 * Math.pow(random.nextDouble(), bias));
这是很有用的,因为您可以调整
偏差
来调整较稀有项目的“稀有性”。偏差>1将有利于较低的数字,<1将有利于较高的数字,1将是统一的

例如,
randomBiasted(100,2.0)
将给出与Tim B的答案相同的结果分布


还请注意,可以使用将[0,1]映射到[0,1]的任何函数来修改偏移;例如,可以使用立方体使所有结果偏离中心(请参见):

另一个例子是,您可以使用
Math.abs(random.nextGaussian())
来获得高斯分布的一半(参见Christian的答案)。需要注意的是,您必须不断尝试,直到得到一个小于1的数字(它可能超出范围[-1,1])。但是,您可以通过添加可根据口味调整的缩放参数来利用较大的范围:

int randomGaussian (int max, float scale) { 
    double v;
    do {
        v = Math.abs(random.nextGaussian() / scale);
    } while (v >= 1.0);
    return (int)(v * max);
}
说实话,在看了下面的测试结果后,我个人喜欢具有更高标度值的高斯分布——稀有项变得更稀有,但不像指数分布那样对普通项有强烈的偏见


更新:我在上创建了一个项目,演示了上面列出的方法。下面是一个30个值的10000个示例:

Name :  Uniform  Pow(0.5)  Pow(2.0) Pow(10.0)    G(1.0)    G(3.5)     Cubic 
0    :      337        11      1872      7118       365       946      1126 
1    :      359        33       744       511       406       939       517 
2    :      327        60       589       328       360       876       407 
3    :      330       101       458       224       370       846       307 
4    :      347       103       445       170       395       817       310 
5    :      344       131       366       141       374       727       257 
6    :      326       148       358       147       416       691       275 
7    :      326       180       309       106       373       645       254 
8    :      314       195       295       129       335       575       282 
9    :      331       227       311        79       356       506       219 
10   :      329       245       325        84       376       458       258 
11   :      340       241       230        75       370       366       228 
12   :      367       290       251        75       366       320       215 
13   :      343       294       264        70       345       243       237 
14   :      313       317       256        60       344       211       224 
15   :      346       331       240        66       358       186       210 
16   :      353       363       204        48       338       131       226 
17   :      329       373       213        55       344       157       193 
18   :      323       417       200        57       327        86       230 
19   :      323       446       219        56       354        75       208 
20   :      321       466       211        43       296        56       209 
21   :      339       496       205        40       297        34       267 
22   :      338       484       192        48       278        37       237 
23   :      335       523       168        46       290        19       306 
24   :      327       571       162        31       251        18       279 
25   :      322       573       216        49       263         7       302 
26   :      323       580       152        35       277        11       311 
27   :      333       596       209        41       268         9       354 
28   :      316       590       158        38       250         6       495 
29   :      339       615       178        30       258         2      1057 

请注意,对于
Math.pow(),您确实可以使用高偏移值使稀有对象变得稀有
方法或高斯方法的高标度值。这也显示了立方S曲线偏离中心的偏差。

是的,基本上需要更改概率分布。有几种方法可以做到这一点,但最简单的方法之一就是在前后使用非线性标度因子

i、 e.代替

int i = random.nextInt(100);
你可以:

int i = Math.sqrt(random.nextInt(100*100));
随机数在整个范围内给你一个均匀分布,但平方根会在你上升时将数字压缩在一起,所以更高的数字更有可能。你总是可以做100-i,然后返回到更低的数字,可能性更大,你可以改变曲线的陡度来调整概率

*

另一种方法(更容易控制)是使用随机数的组合。基本上,不是从0-100中选择一个数字,而是从0-50中选择两个数字,然后将它们相加,或者三个数字,或者四个数字。你选择的滚动次数越多,组合的次数越多,曲线越陡峭

这将使赔率朝着桌子的中心加权,0和100变得同样不可能,50变得可能。你可以使用它并在两端放置不可能的东西,或者你可以生成两倍于你需要的范围的数字,如果超出范围,则翻转它

i、 e

您可以尝试使用(或高斯分布):

注意:正如@JasonC所提到的,此方法也会给出负数,因此您可能需要使用
Math.abs()

Math.abs(rand.nextGaussian())
可用于生成偏向低端的正数。
int i = Math.sqrt(random.nextInt(100*100));
int i = random.nextInt(100)+random.nextInt(100);
if (i > 100) {
   i = 200-i;
}
Random rand = new Random();
chance = rand.nextGaussian();
chance = Math.abs(rand.nextGaussian());