What Is a Seed in Terms of Generating a Random Number

What is a seed in terms of generating a random number?

What is normally called a random number sequence in reality is a "pseudo-random" number sequence because the values are computed using a deterministic algorithm and probability plays no real role.

The "seed" is a starting point for the sequence and the guarantee is that if you start from the same seed you will get the same sequence of numbers. This is very useful for example for debugging (when you are looking for an error in a program you need to be able to reproduce the problem and study it, a non-deterministic program would be much harder to debug because every run would be different).

If you need just a random sequence of numbers and don't need to reproduce it then simply use current time as seed... for example with:

srand(time(NULL));

What's the difference between a random number generator's seed and state?

Disclaimer: I am not an expert regarding the theoretical aspect of random number generators, most of the content below actually comes from the C++ standard itself.

The state Xi of a generator, is the actual internal state of a generator - the (minimal) information you need to generate the next state and the next value of the generator:

  • you transition from one state to another using a "transition" function, Xi+1 = TA(Xi);
  • you generate a value by using a "generation" function, GA(Xi).

The seed S is a "value" used to generate the first state X0.

The state of a generator is inherent to it (see below), two implementations of the same generator will have the same state (in a theoretical sense), but may require completely different seeds.

In C++, you seed a Mersenne Twister engine using a single value, while its state is a sequence of integers... I could choose to implement a Mersenne Twister engine that could only be seed by a sequence of integer (that would become the first state).


Some examples from the standard random library to better understand:

A linear congruential generator is simply a generator that follows a recursive relation of the form:

X i+1 = TA(Xi) = (a . Xi + c) mod m

Where a, c and m are parameters of the generator. In this case:

  • the state of the engine is simply the current value of Xi;
  • the seed is the value of X0;

...when you seed the generator with a value k, you actually simply set Xi = k.

But there are other generators, e.g. in the C++11 standard random library, you will find Mersenne Twister (MT) generators.

I am certainly not an expert on Mersenne Twister generator, but from the c++ draft, you can see that:

  • the state of a MT generator is actually a sequence of integer Xi = (Xi,0, Xi, 1, ...);
  • the seed for a MT (in the standard) is actually a single value;

...when you seed the generator with a value k, you actually perform "complex" operations1 to compute X0 from k, but X0 is certainly not k.

1 I will not go into details for these operations, because I do not really know them, but you can look at the standard to see how the state (sequence) is generated from the seed.

random.seed(): What does it do?

Pseudo-random number generators work by performing some operation on a value. Generally this value is the previous number generated by the generator. However, the first time you use the generator, there is no previous value.

Seeding a pseudo-random number generator gives it its first "previous" value. Each seed value will correspond to a sequence of generated values for a given random number generator. That is, if you provide the same seed twice, you get the same sequence of numbers twice.

Generally, you want to seed your random number generator with some value that will change each execution of the program. For instance, the current time is a frequently-used seed. The reason why this doesn't happen automatically is so that if you want, you can provide a specific seed to get a known sequence of numbers.

What is seed in util.Random?

A pseudo-random number generator produces a sequence of numbers. It
isn't truly random, but generally a mathematical calculation which
produces an output that matches some desirable distribution, and
without obvious patterns. In order to produce such a sequence, there
must be state stored for the generator to be able to generate the next
number in that sequence. The state is updated each time using some
part of the output from the previous step.

Seeding explicitly initialises this state. A 'seed' is a starting
point, from which something grows. In this case, a sequence of
numbers.

This can be used either to always generate the same sequence (by using
a known constant seed), which is useful for having deterministic
behaviour. This is good for debugging, for some network applications,
cryptography, etc.

Or, in situations where you want the behaviour to be unpredictable
(always different each time you run a program, a card game perhaps),
you can seed with a number likely to be continually changing, such as
time.

The 'randomness' of the sequence does not depend on the seed chosen,
though it does depend on not reseeding the sequence.

Taken from What is a seed in relation to a random number generation algorithm and why is computer time used to create this seed more often than not?

This should answer your question.

How to properly seed random number generator

Each time you set the same seed, you get the same sequence. So of course if you're setting the seed to the time in a fast loop, you'll probably call it with the same seed many times.

In your case, as you're calling your randInt function until you have a different value, you're waiting for the time (as returned by Nano) to change.

As for all pseudo-random libraries, you have to set the seed only once, for example when initializing your program unless you specifically need to reproduce a given sequence (which is usually only done for debugging and unit testing).

After that you simply call Intn to get the next random integer.

Move the rand.Seed(time.Now().UTC().UnixNano()) line from the randInt function to the start of the main and everything will be faster. And lose the .UTC() call since:

UnixNano returns t as a Unix time, the number of nanoseconds elapsed since January 1, 1970 UTC.

Note also that I think you can simplify your string building:

package main

import (
"fmt"
"math/rand"
"time"
)

func main() {
rand.Seed(time.Now().UnixNano())
fmt.Println(randomString(10))
}

func randomString(l int) string {
bytes := make([]byte, l)
for i := 0; i < l; i++ {
bytes[i] = byte(randInt(65, 90))
}
return string(bytes)
}

func randInt(min int, max int) int {
return min + rand.Intn(max-min)
}

Java random numbers using a seed

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


Related Topics



Leave a reply



Submit