Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更好的整数随机数发生器_Java_Random - Fatal编程技术网

Java 更好的整数随机数发生器

Java 更好的整数随机数发生器,java,random,Java,Random,目前,我正在使用随机数生成JPanel中组件的位置。我发现使用Random.nextInt(6000)返回了太多小于100的数字,太多,我的意思是绝大多数数字都小于100。因此,我研究了它,发现了一个使用Long的高质量随机数生成器,因此我冒昧地对它进行了正确的格式化(请参见下面的实现)。在那之后,我得到了太多1000-2000范围内的数字 在使用计数器变量进行测试后,当我生成2000个数字时,其中大约1350个在该范围内 我需要一个更随机的数字生成器,甚至是一个真正随机的数字生成器(我不希望得

目前,我正在使用随机数生成JPanel中组件的位置。我发现使用
Random.nextInt(6000)返回了太多小于100的数字,太多,我的意思是绝大多数数字都小于100。因此,我研究了它,发现了一个使用
Long
的高质量随机数生成器,因此我冒昧地对它进行了正确的格式化(请参见下面的实现)。在那之后,我得到了太多1000-2000范围内的数字

在使用计数器变量进行测试后,当我生成2000个数字时,其中大约1350个在该范围内

我需要一个更随机的数字生成器,甚至是一个真正随机的数字生成器(我不希望得到,但如果我能得到的话会更好)

随机类别:

public class HighQualityRandom extends Random {
private static final long serialVersionUID = 1L;

private Lock l = new ReentrantLock();
  private long u;
  private long v = 4101842887655102017L;
  private long w = 1;

  public HighQualityRandom() {
    this(System.nanoTime());
  }
  public HighQualityRandom(long seed) {
    l.lock();
    u = seed ^ v;
    nextLong();
    v = u;
    nextLong();
    w = v;
    nextLong();
    l.unlock();
  }

  public long nextLong() {
    l.lock();
    try {
      u = u * 2862933555777941757L + 7046029254386353087L;
      v ^= v >>> 17;
      v ^= v << 31;
      v ^= v >>> 8;
      w = 4294957665L * (w & 0xffffffff) + (w >>> 32);
      long x = u ^ (u << 21);
      x ^= x >>> 35;
      x ^= x << 4;
      long ret = (x + v) ^ w;
      return ret;
    } finally {
      l.unlock();
    }
  }

  public int next(int bits) {
    return (int) (nextLong() >>> (64-bits));
  }

}

平均而言,约有37-40人(1000人中)不到100人。所以我错了,肯定不是50%都在盒子上或盒子外。但是:在可供选择的
28311552
可能的解决方案(地图为6144x4608)中,似乎太多了,无法停留在我不知道您在做什么,但这里有一个小示例程序:

Random r = new Random();
int count = 0;
for (int i = 0; i < 1000_000; i++)
    if (r.nextInt(6000) < 100)
        count++;
System.out.println(count);
理想情况下是:
100/5999*1000000=16669
。我认为这很接近

你做错了什么。请发布原始代码,证明
Random.nextInt(6000)
在超过50%的情况下给出的值小于100

为了在游戏中生成随机数,这是非常好的。也有,但你不需要为游戏,而且它是显着较慢

编辑:

编辑:您总是在创建一个新的
Random
实例!不要那样做。如果总是创建一个新的
Random
实例,并且没有指定种子值,则将根据计算机的当前时间对其进行种子设定。这本身将减少生成器的“随机性”

如我的示例所示:创建一个
Random
实例,可以选择将其播种到任何您想要的地方,并始终使用它

编辑#2:

种子:它有点像随机数生成器的“状态”。从
随机
类javadoc中引用:

如果使用相同的种子创建了两个Random实例,并且对每个实例进行了相同的方法调用序列,则它们将生成并返回相同的数字序列


实际上,如果要复制相同的序列,只需设置种子。例如,您保存了一个游戏/重播,并希望重新播放该游戏。在这种情况下,您会将起始种子与游戏/重播一起保存,当再次玩游戏时,您会设置保存的种子,从而获得相同的随机序列。

您的数字剥离问题导致了您的问题。XOR移位生成器工作正常,但其范围是64位——2的幂次方,而不是10的幂次方,因此没有理由认为其输出的十进制数字是随机的。因此,取随机值并使用mod(10000),而不是选择十进制数字


99%的程序员对数学理解不足,无法改进RNG或密码。不幸的是,大约10%的程序员认为他们在这1%的人能做到。寓意:不要弄乱RNG,只需按预期使用它,并仔细阅读文档。

请先展示一个简短但完整的程序,演示
Random.nextInt
的问题。我强烈怀疑问题是否出在库随机数生成器上
Random
在加密方面可能不强,但它肯定不会在您观察的方式上产生偏差。如果您得到的数字太多,小于100(或在1000-2000范围内),那么问题几乎肯定在于您如何使用该软件包。请向我们展示该代码,而不是无法解决您的问题的替代PRNG。@ControlAltDel,这就是为什么我说我不希望有真正的随机数生成器。你链接的最后一句话。是的,我们不相信你!哈哈。另外,试试ThreadLocalRandom,它应该会更快。@NicholasEason,你也会检查我所做的编辑。我在我的问题中问过,但每个人似乎都忽略了它。。什么是种子?随机化种子似乎已经将计数减少到32-35。这是一个好的做法吗?@Nicholasason实际上,如果你想复制相同的序列,你只需要设定种子。例如,请参见编辑。要使您的计数接近理想值,唯一需要的是有一个
Random
实例,并且不要每次都创建一个随机数。挑剔:如果模恰好不是2的幂,使用模的建议也不会产生完全均匀的分布。更小的数字仍然会有更高的频率,如果你想象一个只提供14位随机性(0-16383)的RNG,并从那里取模,这是显而易见的。0-6383范围内的数字出现的几率是6384-9999数字的两倍。模并不是偏置问题的通用解决方案,这让你下面的咆哮有些讽刺。我的目标不是“改进”RNG,而是将其格式化为4位整数。是的,常用的方法是使用模。它并不像前面指出的那样完美,但在64位时就足够了。如果你真的需要完美,你必须做拒绝抽样。
    public int getRandomX(){
    Random ran = new Random();
    int rand = ran.nextInt(6144);

    if(rand <= 100){
        Game.between++;
    }

    return rand;
}
public int getRandomY(){
    Random ran = new Random();
    int rand = ran.nextInt(4608);

    if(rand <= 100){
        Game.between++;
    }
    System.out.println(Game.between);

    return rand;
}
Random r = new Random();
int count = 0;
for (int i = 0; i < 1000_000; i++)
    if (r.nextInt(6000) < 100)
        count++;
System.out.println(count);
16655