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());