mardi 12 mai 2015

Better random number generator for Integers

Currently, I'm using random numbers to generate positions of components in a JPanel. I found that using Random.nextInt(6000); returned too many numbers that were less than 100, by too many, I mean the greater majority of them were less than 100. So I looked into it, and found a higher quality Random Number Generator that uses Long so I took the liberty to format it properly (See implementation below). After that I'm getting too many numbers in the 1000-2000 range.

After testing with a counter variable, when I generate 2000 numbers around 1350 of them are inside of that range.

I need a number generator that is more random, or even one that is truly random (which I don't expect to get, but would be nice if I could get).

Random Class:

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

}

Implementation:

    public int getRandomX(){
    HighQualityRandom ran = new HighQualityRandom();
    int rand = (int) ran.nextLong();
    String p = rand + "";
    if(rand < 0){
        rand = rand * -1;
    }
    p = rand + "";
    p = p.substring(0, 4);
    rand = Integer.parseInt(p);
    while(rand > 6144){
        rand = (int) ran.nextLong();
        p = rand + "";
        if(rand < 0){
            rand = rand * -1;
        }
        p = rand + "";
        p = p.substring(0,4);
        rand = Integer.parseInt(p);
    }
    System.out.print("X is: " + rand + " Y is: ");
    return rand;
}
public int getRandomY(){
    HighQualityRandom ran = new HighQualityRandom();
    int rand = (int) ran.nextLong();
    String p = rand + "";
    if(rand < 0){
        rand = rand * -1;
    }
    p = rand + "";
    p = p.substring(0, 4);
    rand = Integer.parseInt(p);
    while(rand > 4608){
        rand = (int) ran.nextLong();
        p = rand + "";
        if(rand < 0){
            rand = rand * -1;
        }
        p = rand + "";
        p = p.substring(0,4);

        rand = Integer.parseInt(p);
    }
    System.out.println(rand);
    return rand;
}

As an explanation for what I'm doing to the long to get my 4 digit number:

  1. If it's negative, multiply by negative 1.
  2. Make it a String.
  3. Substring the first 4 digits
  4. If it's too big: do it again.

As a side note, what is the seed parameter supposed to be in the Random class? I tried googling it and people were talking about encryption stuff...

Aucun commentaire:

Enregistrer un commentaire