I know if i use the Random generator from Java, generating numbers with nextInt, the numbers will be uniformly distributed. But what happens if I use 2 instances of Random, generating numbers with the both Random classes. The numbers will be uniformly distributed or not?
The numbers generated by each Random instance will be uniformly distributed, so if you combine the sequences of random numbers generated by both Random instances, they should be uniformly distributed too.
Note that even if the resulting distribution is uniform, you might want to pay attention to the seeds to avoid correlation between the output of the two generators. If you use the default no-arg constructor, the seeds should already be different. From the source code of java.util.Random:
private static volatile long seedUniquifier = 8682522807148012L;
public Random() { this(++seedUniquifier + System.nanoTime()); }
If you are setting the seed explicitly (by using the Random(long seed) constructor, or calling setSeed(long seed)), you'll need to take care of this yourself. One possible approach is to use a random number generator to produce the seeds for all other generators.
Well, if you seed both Random instances with the same value, you will definitely not get quality discrete uniform distribution. Consider the most basic case, which literally prints the exact same number twice (doesn't get much less random than that ...):
public class RngTest2 {
public static void main(String[] args) throws Exception {
long currentTime = System.currentTimeMillis();
Random r1 = new Random(currentTime);
Random r2 = new Random(currentTime);
System.out.println(r1.nextInt());
System.out.println(r2.nextInt());
}
}
But that's just a single iteration. What happens if we start cranking up the sample size?
Here is a scatter plot of a distribution from running two same-seeded RNGs side-by-side to generate 2000 numbers total:
And here is a distribution of running a single RNG to generate 2000 numbers total:
It seems pretty clear which approach produced higher quality discrete uniform distribution over this finite set.
Now almost everyone knows that seeding two RNGs with the same seed is a bad idea if you're looking for high quality randomness. But this case does make you stop and think: we have created a scenario where each RNG is independently emitting fairly high quality randomness, but when their output is combined it is notably lower in quality (less discrete.)
Related
For example the code below. It has a random class. However it always produce the same output everywhere . In this case which item is the seed?
source: link
import java.util.Random;
public class RandomTest {
public static void main(String[] s) {
Random rnd1 = new Random(42);
Random rnd2 = new Random(42);
System.out.println(rnd1.nextInt(100)+" - "+rnd2.nextInt(100));
System.out.println(rnd1.nextInt()+" - "+rnd2.nextInt());
System.out.println(rnd1.nextDouble()+" - "+rnd2.nextDouble());
System.out.println(rnd1.nextLong()+" - "+rnd2.nextLong());
}
}
42 is the seed, as the very same Javadoc says. So, what is a seed? A random number is seldom truly random - often it's a pseudo-random instead. This means it's generated from a function, which is said PRNG (pseudo random number genrator). Being generated from a function, in turn, means that the output is not random anymore, since it's predictable!
However, depending on your needs, this pseudo-randomness may be enough - I said enough because generating random bit is expensive, and I'm not talking about time or memory, but about money (see this link on wikipedia). So, for example, if you need a random value to place enemies in your game, a pseudo-random number is ok - but if your are building security-related software, you want to use a true random number, or at least a cryptographically secure PRNG.
How can we describe a PRNG, like the one used in Math.random()? It's a function, initialized with a seed S that returns an array of values A. Note that, for each integer S, is defined one and only one array A. For example (values are not actual):
first call second call third call
seed: 14329 .18 .82 .5
seed: 3989 .7 .02 .93
So you seed you PRNG with some known value when you want its result to be predictable - for example for testing purposes or to ensure that, each time you run level 1 in your game, the enemies are always placed in the same (pseudo) random places - otherwise you don't need to explicitely pass a seed.
Random Seed on Wikipedia:
A random seed (or seed state, or just seed) is a number (or vector)
used to initialize a pseudorandom number generator.
In other word, it is the number from which a seem-to-be-random sequence will be generated. Therefore, if you use the same number, the senquence will always be the same.
In practice, we usually use System Time as seed.
The seed is given as the argument of the constructor of Random; using the same seed will yield the same sequence of numbers. However this is discussed under the link in thet question.
In this case the seed is 42. This is the reason for the same output - you use the same seed.
You can use for example
Random rnd1 = new Random(System.currentTimeMillis())
for different outputs.
The seed is the initial value of the internal state of the pseudorandom number generator which is maintained by method next(int).
The invocation new Random(seed) is equivalent to:
Random rnd = new Random();
rnd.setSeed(seed);
From the Java documentation in the Random class
Creates a new random number generator using a single long seed. The seed is the initial value of the internal state of the pseudorandom number generator which is maintained by method next(int).
The invocation new Random(seed) is equivalent to:
Random rnd = new Random();
rnd.setSeed(seed);
So 42 is the seed given to the new Random() in your example
Let's assume I have a reliably truly random source of random numbers, but it is very slow. It only give me a few hundreds of numbers every couple of hours.
Since I need way more than that I was thinking to use those few precious TRN I can get as seeds for java.util.Random (or scala.util.Random). I also always will pick a new one to generate the next random number.
So I guess my questions are:
Can the numbers I generate from those Random instance in Java be considered truly random since the seed is truly random?
Is there still a condition that is not met for true randomness?
If I keep on adding levels at what point will randomness be lost?
Or (as I thought when I came up with it) is truly random as long as the stream of seeds is?
I am assuming that nobody has intercepted the stream of seeds, but I do not plan to use those numbers for security purposes.
For a pseudo random generator like java.util.Random, the next generated number in the sequence becomes predictable given only a few numbers from the sequence, so you will loose your "true randomness" very fast. Better use one of the generators provided by java.security.SecureRandom - these are all strong random generators with an VERY long sequence length, which should be pretty hard to be predicted.
Our java Random gives uniformly spread random numbers. That is not true randomness, which may yield five times the same number.
Furthermore for every specific seed the same sequence is generated (intentionally). With 2^64 seeds in general irrelevant. (Note hackers could store the first ten numbers of every sequence; thereby rapidly catching up.)
So if you at large intervals use a truely random number as seed, you will get a uniform distribution during that interval. In effect not very different from not using the true randomizers.
Now combining random sequences might reduce the randomness. Maybe translating the true random number to bytes, and xor-ing every new random number with another byte, might give a wilder variance.
Please do not take my word only - I cannot guarantee the mathematical correctness of the above. A math/algorithmic forum might give more info.
When you take out more bits, than you have put in they are for sure no longer truly random. The break point may even occur earlier if the random number generator is bad. This can be seen by considering the entropy of the sequences. The seed value determines the sequence completely, so there are at most as many sequences as seed values. If they are all distinct, the entropy is the same as that of the seeds (which is essentially the number of seed bits, assuming the seed is truly random).
However, if different seeds lead to the same pseudo random sequence the entropy of the sequences will be lower than that of the seeds. If we cut off the sequences after n bits, the entropy may be even lower.
But why care if you don't use it for security purposes? Are you sure the pseudo random numbers are not good enough for your application?
I discovered something strange with the generation of random numbers using Java's Random class.
Basically, if you create multiple Random objects using close seeds (for example between 1 and 1000) the first value generated by each generator will be almost the same, but the next values looks fine (i didn't search further).
Here are the two first generated doubles with seeds from 0 to 9 :
0 0.730967787376657 0.24053641567148587
1 0.7308781907032909 0.41008081149220166
2 0.7311469360199058 0.9014476240300544
3 0.731057369148862 0.07099203475193139
4 0.7306094602878371 0.9187140138555101
5 0.730519863614471 0.08825840967622589
6 0.7307886238322471 0.5796252073129174
7 0.7306990420600421 0.7491696031336331
8 0.7302511331990172 0.5968915822372118
9 0.7301615514268123 0.7664359929590888
And from 991 to 1000 :
991 0.7142160704801332 0.9453385235522973
992 0.7109015598097105 0.21848118381994108
993 0.7108119780375055 0.38802559454181795
994 0.7110807233541204 0.8793923921785096
995 0.7109911564830766 0.048936787999225295
996 0.7105432327208906 0.896658767102804
997 0.7104536509486856 0.0662031629235198
998 0.7107223962653005 0.5575699754613725
999 0.7106328293942568 0.7271143712820883
1000 0.7101849056320707 0.574836350385667
And here is a figure showing the first value generated with seeds from 0 to 100,000.
First random double generated based on the seed :
I searched for information about this, but I didn't see anything referring to this precise problem. I know that there is many issues with LCGs algorithms, but I didn't know about this one, and I was wondering if this was a known issue.
And also, do you know if this problem only for the first value (or first few values), or if it is more general and using close seeds should be avoided?
Thanks.
You'd be best served by downloading and reading the Random source, as well as some papers on pseudo-random generators, but here are some of the relevant parts of the source. To begin with, there are three constant parameters that control the algorithm:
private final static long multiplier = 0x5DEECE66DL;
private final static long addend = 0xBL;
private final static long mask = (1L << 48) - 1;
The multiplier works out to approximately 2^34 and change, the mask 2^48 - 1, and the addend is pretty close to 0 for this analysis.
When you create a Random with a seed, the constructor calls setSeed:
synchronized public void setSeed(long seed) {
seed = (seed ^ multiplier) & mask;
this.seed.set(seed);
haveNextNextGaussian = false;
}
You're providing a seed pretty close to zero, so initial seed value that gets set is dominated by multiplier when the two are OR'ed together. In all your test cases with seeds close to zero, the seed that is used internally is roughly 2^34; but it's easy to see that even if you provided very large seed numbers, similar user-provided seeds will yield similar internal seeds.
The final piece is the next(int) method, which actually generates a random integer of the requested length based on the current seed, and then updates the seed:
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
This is called a 'linear congruential' pseudo-random generator, meaning that it generates each successive seed by multiplying the current seed by a constant multiplier and then adding a constant addend (and then masking to take the lower 48 bits, in this case). The quality of the generator is determined by the choice of multiplier and addend, but the ouput from all such generators can be easily predicted based on the current input and has a set period before it repeats itself (hence the recommendation not to use them in sensitive applications).
The reason you're seeing similar initial output from nextDouble given similar seeds is that, because the computation of the next integer only involves a multiplication and addition, the magnitude of the next integer is not much affected by differences in the lower bits. Calculation of the next double involves computing a large integer based on the seed and dividing it by another (constant) large integer, and the magnitude of the result is mostly affected by the magnitude of the integer.
Repeated calculations of the next seed will magnify the differences in the lower bits of the seed because of the repeated multiplication by the constant multiplier, and because the 48-bit mask throws out the highest bits each time, until eventually you see what looks like an even spread.
I wouldn't have called this an "issue".
And also, do you know if this problem only for the first value (or first few values), or if it is more general and using close seeds should be avoided?
Correlation patterns between successive numbers is a common problem with non-crypto PRNGs, and this is just one manifestation. The correlation (strictly auto-correlation) is inherent in the mathematics underlying the algorithm(s). If you want to understand that, you should probably start by reading the relevant part of Knuth's Art of Computer Programming Chapter 3.
If you need non-predictability you should use a (true) random seed for Random ... or let the system pick a "pretty random" one for you; e.g. using the no-args constructor. Or better still, use a real random number source or a crypto-quality PRNG instead of Random.
For the record:
The javadoc (Java 7) does not specify how Random() seeds itself.
The implementation of Random() on Java 7 for Linux, is seeded from the nanosecond clock, XORed with a 'uniquifier' sequence. The 'uniquifier' sequence is LCG which uses different multiplier, and whose state is static. This is intended to avoid auto-correlation of the seeds ...
This is a fairly typical behaviour for pseudo-random seeds - they aren't required to provide completely different random sequences, they only provide a guarantee that you can get the same sequence again if you use the same seed.
The behaviour happens because of the mathematical form of the PRNG - the Java one uses a linear congruential generator, so you are just seeing the results running the seed through one round of the linear congruential generator. This isn't enough to completely mix up all the bit patterns, hence you see similar results for similar seeds.
Your best strategy is probably just to use very different seeds - one option would be to obtain these by hashing the seed values that you are currently using.
By making random seeds (for instance, using some mathematical functions on System.currentTimeMillis() or System.nanoTime() for seed generation) you can get better random result. Also can look at here for more information
I have piece of code which generates some Random number and prints out on console. However I am curious about the pattern which it prints, Such as,
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Random random = new Random(-6732303926L);
for(int i=0;i<10;i++)
System.out.println(random.nextInt(10)+" ");
}
}
Result : 0 1 2 3 4 5 6 7 8 9 - Every number in new line.
And if you change this code a bit! like,
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Random random = new Random(-6732303926L);
for(int i=0;i<10;i++)
System.out.println(random.nextInt(11)+" ");
}
}
Result : 8 9 2 2 10 3 8 7 0 10 - Every number in new line.
What is the reason of 0123456789 which is not random at all!?
0123456789 is random too, in this case - it's about as likely to come up as 14235682907, which would no doubt not have given you any cause for concern.
You spotted a fluke, basically. If you print the next 10 numbers in the first case, they're not preserving any obvious order.
It's like flipping a coin - the pattern HHHHHHHH is just as likely to come up as the exact pattern HHTHTTHH; there's a 1 in 28 chance of each coming up, as at any of the 8 steps there's a 50% chance of it going wrong. But the first pattern looks like it's broken, whereas the second doesn't.
I think it is random... you are using a specific seed for the random function. You just found the seed that will give you the numbers 0 - 9, in order.
EDIT: Apparently, this is the algorithm:
The java.util.Random class implements what is generally called a linear congruential generator (LCG). An LCG is essentially a formula of the following form:
numberi+1 = (a * numberi + c) mod m
Source: here
The Random class is a pseudo-random number generator. Thus it is not truely random, but instead relies on mathematical operations performed on an initial seed value. Thus, certain seeds will produce certain (potentially interesting/fun) sequences
The reason for the sequence is so that one can test software by making Random predicable with predictable and repeatable sequences using its next methods. Whenever a particular long seed parameter is a parameter to the Random constructor, the instanced Random object is supposed to return the same sequences of values through its next methods. This is a deliberate feature of java.util.Random.
java.util.Random has two constructors:
Random()
and
Random(long seed)
The constructor without a long integer seed uses the system time for creating a seed value for the pseudo random number generator. No two instantiations of Random will use the same seed and you should get a very good pseudo-random sequence. A Random instantiation using the constructor without a seed creates an instance with unpredictable sequences of values that will be pseudo-random.
The constructor with a seed value is intended only for making Random deterministic with predictable sequences using its next methods. The typical use of a seed is for software test purposes where results must be predicable and repeatable. Every instance of Random that uses the same long seed integer will create the same sequence of results every time. The particular long you used causes the sequence to be 0 1 2 3 4 5 6 7 8 9 over and over again when getting one of 10 integer values using nextInt(10) method. This and other predictable sequences that are repeatable every time software executes are very useful for testing software and are not meant for creating unpredictable pseudo-random sequences.
Creating random with a seed ensures a certain behavior. Especially, creating two instances of Random with the same seed, will always behave identically. Someone found out (via brute force, I guess) that using this particular seed together with the first 10 nextInt(10), creates such a seemingly ordered sequence. This sequence is pseudo-random updon first creation, but can be reproduced. Changing anything in the slightest gives a different result.
Random is based on the seed you give to it, if you want to get true random numbers, use time functions as seeds, and you'll get a real random number series.
Reference: link text
i cannot understand the following line , can anybody provide me some example for the below statement?
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers
Since you asked for an example:
import java.util.Random;
public class RandomTest {
public static void main(String[] s) {
Random rnd1 = new Random(42);
Random rnd2 = new Random(42);
System.out.println(rnd1.nextInt(100)+" - "+rnd2.nextInt(100));
System.out.println(rnd1.nextInt()+" - "+rnd2.nextInt());
System.out.println(rnd1.nextDouble()+" - "+rnd2.nextDouble());
System.out.println(rnd1.nextLong()+" - "+rnd2.nextLong());
}
}
Both Random instances will always have the same output, no matter how often you run it, no matter what platform or what Java version you use:
30 - 30
234785527 - 234785527
0.6832234717598454 - 0.6832234717598454
5694868678511409995 - 5694868678511409995
The random generator is deterministic. Given the same input to Random and the same usage of the methods in Random, the sequence of pseudo-random numbers returned to your program will be the same even in different runs on different machines.
This is why it is pseudo-random - the numbers returned behave statistically like random numbers except they can be reliably predicted. True random numbers are unpredictable.
The Random class basically is a Psuedorandom Number Generator (also known as Deterministic random bit generator) that generates a sequence of numbers that approximates the properties of random numbers. It's not generally random but deterministic as it can be determined by small random states in the generator (such as seed). Because of the deterministic nature, you can generate identical result if you the sequence of methods and seeds are identical on 2 generators.
The numbers are not really random, given the same starting conditions (the seed) and the same sequence of operations, the same sequence of numbers will be generated. This is why it would not be a good iea to use the basic Random class as part of any cryptograhic or security related code since it may be possible for an attacker to figure out which sequnce is being generated and predict future numbers.
For a random number generator that emits non-deterministic values, take a look at SecureRandom.
See Random number generation, Computational methods on wikipedia for more info.
This means that when you create the Random object (e.g. at the start of your program), you will probably want to start with a new seed. Mostly people choose some time related value, such as the number of ticks.
The fact that the number sequences are the same given the same seed is actually very convenient if you want to debug your program: make sure you log the seed value and if something is wrong you can restart the program in the debugger using that same seed value. This means you can replay the scenario exactly. This would be impossible if you would (could) use a true random number generator.
With the same seed value, separate instances of Random will return/generate the same sequence of random numbers; more on this here:
http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Tech/Chapter04/javaRandNums.html
Ruby Example:
class LCG; def initialize(seed=Time.now.to_i, a=2416, b=374441, m=1771075); #x, #a, #b, #m = seed % m, a, b, m; end; def next(); #x = (#a * #x + #b) % #m; end; end
irb(main):004:0> time = Time.now.to_i
=> 1282908389
irb(main):005:0> r = LCG.new(time)
=> #<LCG:0x0000010094f578 #x=650089, #a=2416, #b=374441, #m=1771075>
irb(main):006:0> r.next
=> 45940
irb(main):007:0> r.next
=> 1558831
irb(main):008:0> r.next
=> 1204687
irb(main):009:0> f = LCG.new(time)
=> #<LCG:0x0000010084cb28 #x=650089, #a=2416, #b=374441, #m=1771075>
irb(main):010:0> f.next
=> 45940
irb(main):011:0> f.next
=> 1558831
irb(main):012:0> f.next
=> 1204687
Based on the values a/b/m, the result will be the same for a given seed. This can be used to generate the same "random" number in two places and both sides can depend on getting the same result. This can be useful for encryption; although obviously, this algorithm isn't cryptographically secure.