62

This is my code to generate random numbers using a seed as an argument:

double randomGenerator(long seed) {
    Random generator = new Random(seed);
    double num = generator.nextDouble() * (0.5);

    return num;
}

Every time I give a seed and try to generate 100 numbers, they all are the same.
How can I fix this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rahul Bhatia
  • 1,005
  • 2
  • 13
  • 18
  • 4
    That is what a seed is supposed to do. You are only generating one number for a seed. What are you trying to achieve? – Peter Lawrey Sep 17 '12 at 11:48
  • 2
    possible duplicate of [Java random always returns the same number when I set the seed?](http://stackoverflow.com/questions/5533191/java-random-always-returns-the-same-number-when-i-set-the-seed) – finnw Sep 17 '12 at 14:30
  • 4
    You can use `System.currentTimeMillis()` as the seed to produce random results. Not giving any seed also produces random results. I'm not sure if it would start repeating at some point if you don't give any seed. – WVrock Nov 09 '14 at 10:32

7 Answers7

92

If you're giving the same seed, that's normal. That's an important feature allowing tests.

Check this to understand pseudo random generation and seeds:

Pseudorandom number generator

A pseudorandom number generator (PRNG), also known as a deterministic random bit generator DRBG, is an algorithm for generating a sequence of numbers that approximates the properties of random numbers. The sequence is not truly random in that it is completely determined by a relatively small set of initial values, called the PRNG's state, which includes a truly random seed.

If you want to have different sequences (the usual case when not tuning or debugging the algorithm), you should call the zero argument constructor which uses the nanoTime to try to get a different seed every time. This Random instance should of course be kept outside of your method.

Your code should probably be like this:

private Random generator = new Random();
double randomGenerator() {
    return generator.nextDouble()*0.5;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Millisecond is a very long time, it would be much safer tu use System.nanoTime() – kukis Oct 26 '15 at 08:28
  • 2
    @kukis It doesn't matter. It's just a number that isn't the same at every **program** launches. Because your program sets the seed only once. – Denys Séguret Oct 26 '15 at 08:29
  • 5
    using "new Random()" is equivalent or better see source: public Random() { this(seedUniquifier() ^ System.nanoTime()); } – dermoritz Jan 01 '16 at 12:28
  • Assume that i have defined new Random(42) in class and in another class i again do new Random() only and i got different result...is there any technique that i can set random seed globally and for every class i get same value for every class even though i initialize new Random(). It will great help if someone can answer. – Gaurav Koradiya May 15 '20 at 07:02
  • @GauravKoradiya that would be a problem, usually, and a clear break of design principles. So no, there's no way. You can either pass your seed or the Random instance to where it's needed. – Denys Séguret May 15 '20 at 11:32
40

The easy way is to use:

Random rand = new Random(System.currentTimeMillis());

This is the best way to generate Random numbers.

Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
Pollar
  • 441
  • 4
  • 2
  • 6
    in special cases when your code runs too fast it is possible to start with the same seed – wutzebaer Aug 30 '18 at 21:09
  • as @dermoritz pointed out: using "new Random()" is better see source: public Random() { this(seedUniquifier() ^ System.nanoTime()); } – Jason Smith Feb 25 '23 at 22:16
11

You shouldn't be creating a new Random in method scope. Make it a class member:

public class Foo {
   private Random random 

   public Foo() {
       this(System.currentTimeMillis());
   }

   public Foo(long seed) {
       this.random = new Random(seed);
   }

   public synchronized double getNext() {
        return generator.nextDouble();
   }
}

This is only an example. I don't think wrapping Random this way adds any value. Put it in a class of yours that is using it.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • This answer is almost completely unrelated to the question. – Chris Mountford Feb 17 '15 at 03:32
  • 7
    It might seem unrelated since it merely seems to be a refactor, but it is definitely related. OP was re-instantiating the Random generator every time the method was called, so `nextDouble` would always return the _first_ double in the random sequence. This answer only instantiates the Random generator once, and each time `getNext` is called it actually steps through the random sequence and returns a different number each time. – Brandon Mar 14 '15 at 05:42
8

That's the principle of a Pseudo-RNG. The numbers are not really random. They are generated using a deterministic algorithm, but depending on the seed, the sequence of generated numbers vary. Since you always use the same seed, you always get the same sequence.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
2

Problem is that you seed the random generator again. Every time you seed it the initial state of the random number generator gets reset and the first random number you generate will be the first random number after the initial state

Minion91
  • 1,911
  • 12
  • 19
1

Several of the examples here create a new Random instance, but this is unnecessary. There is also no reason to use synchronized as one solution does. Instead, take advantage of the methods on the ThreadLocalRandom class:

double randomGenerator() {
    return ThreadLocalRandom.current().nextDouble(0.5);
}
Finn
  • 652
  • 7
  • 16
0

If you'd want to generate multiple numbers using one seed you can do something like this:

public double[] GenerateNumbers(long seed, int amount) {
    double[] randomList = new double[amount];
    for (int i=0;i<amount;i++) {
        Random generator = new Random(seed);
        randomList[i] = Math.abs((double) (generator.nextLong() % 0.001) * 10000);
        seed--;
    }
    return randomList;
}

It will display the same list if you use the same seed.