Select one of three numbers with equal probability? - java

I would like to select one of three numbers with equal probability (33.3%). Can I use the Random class to achieve this?
What would be the percentage of each number being selected after 100x running? Would it be evenly 33.3% each?

Use the Random.nextInt(n) method to select a number between 0 and 2. Use this to choose one of your three values.
int index = Random.nextInt(3);
int selectedValue = myOptions[index];
The value returned by that method is uniformly distributed. So if you were to repeat this process infinitely, the probability of each number being chosen would approach 1/3.
From the docs:
All n possible int values are produced with (approximately) equal probability

You can try somethin like this for 1/25 probabilty
if(new java.util.Random().nextInt(25)==0){
//Do something.
}

Random rand = new Random();
int number = rand.nextInt(3) + 1;
Note that there is no such thing as true random. In computer science, we use so called pseudo-randomness. For most everyday purposes that's close enough to random that the difference isn't noticable. You say you'll be running it 100 times, then yes. For all intents and purposes it will be 33.3333...%.

You need to decide whether entropy is more important than 'randomnes'. Randomness will not give you a perfect 33.3% but the final outcome will be unpredictable. Other algorithms can give you a perfect 33.3% but the outcome can be predictable, and even the same in some cases each time the process is ran.

it is possible for exact random ness for only a two value range.
....after random statemeants...
if(rand=>1&&rand<=1.4999999999999999999999....)
{
rand=1;
}
else
{
rand=2
}

Related

Coin toss using random numbers does not appear exactly random

I wanted a random number generator to simulate a coin toss and here's what i did
public class CoinToss
{
public static void main(String args[])
{
int num=(int)(1000*Math.random());
if(num<500)
System.out.println("H");
else
System.out.println("T");
}
}
The results were discouraging as i got 16 Heads and 4 tails in 20 runs.
That does not appear to be random. Its possible but i want a general opinion if the program is correct ? Am i missing something mathematically ?
Modified your code a little and it seems to be random enough.
code:
int h = 0;
int t = 0;
for (int i = 0; i < 1000; i++) {
int num = (int) (1000 * Math.random());
if (num < 500) {
h++;
} else {
t++;
}
}
System.out.println("T:" + t);
System.out.println("H:" + h);
output:
T:506
H:494
I guess this is the thing with randomness ^^
20 runs is not a big enough sample size to assess how random it is. Think of it this way: if you did 4 runs and got 4 heads, you'd think, "Wow, that's not random at all." But in fact if you took 4 coins, and flipped them 16 times, you'd expect to get all 4 heads at least once. So if you do a small number of runs, and you get results that aren't equally divided between heads and tails, that doesn't mean it's not random.
Or look at it this way: if you wrote some code that just printed "Heads" then "Tails" then "Heads" and so on, you'd get exactly half heads and half tails. But that's not random at all! It's just a repeating pattern.
So the moral of the story is not to be surprised when random results look uneven over short runs. Try re-writing your code so that it counts how many heads and how many tails, and let it flip about a million or so, and see if you don't get about 500,000 each. It should be a little more or a little less, because random doesn't give you exact, but it should be closer.
your code seems to be correct although you could implement it easier:
Random r = new Random();
int num = r.nextInt(2);
if (num == 0)
System.out.println("H");
else
System.out.println("T");
Random#nextInt(int i) returns a random Integer between 0 and i-1
A pseudorandom number generator (PRNG), also known as a deterministic random bit generator (DRBG), is an algorithm for generating a sequence of numbers whose properties approximate the properties of sequences of random numbers.
The PRNG-generated sequence is not truly random, because it is completely determined by a relatively small set of initial values, called the PRNG's seed
Although sequences that are closer to truly random can be generated
Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin. John von Neumann
You need way more inputs in order to get equal number of each. For such small number of outputs sometimes you will get them close to each other in terms of numbers, sometimes one side will "show" way more then other. Actually, probability of having 4 tails and 16 heads is 0.462% which is somewhat "realistic" to happen... Try to play with it more with higher number of runs and see how it behaves.
And btw think about this input:
6 6 6 6 6 6 6 6 6 6
Doesn't seems random, right? But it exist in decimal of number π at some point, so its a part of random series. Its just a question of series size, so you must think in that way when you work with random numbers. Think more about random generator rather than about results. You are using correct function since its based on System.nanoTime(), so generator is right, but your result is to small.

Generate even numbers 1-4 using Math.random()?

I would like to generate the numbers 1-4 (whole integers) using Math.random. I have only succeeded in getting doubles or large doubles, and cannot figure out how to set a limit on the minimum and maximum.
Math.random(); = something between 0-1 as a double?
I have seen some people suggest something like this: num = Math.random() * 60 + 25; but have no idea what that does, or how it works.
I am not sure if this is a true question, and feel free to let me know if I should delete it.
Edit: Is there a way to not get the numbers to repeat, yet still be random every time the program is run?
int rand = (Math.random() * 4) + 1;
Math.Random is redundant here, use the Random class.
Random rand = new Random();
rand.nextInt(4)+1; //starts at 0, so add 1
Import this class by:
import java.util.*; or import java.util.Random;
the random number in math gives you a decimal number between zero and one.
you need to tell it to be within a certain range.
something like:
(4*Math.random())+1 should give you between 1-4 I think. correct me if I am wrong anyone.
Random rand = new Random();
System.out.println(rand.nextInt(4) + 1); // we add 1 because it starts with 0
If you really have to use Math.random you need to multiply (and add).
It's quite basic math, Math.random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.
So multiplying it with X will give a number greater than or equal to 0.0 and less than X. Cast that to an int to get rid of decimals and if you only want even numbers you can do a few things, the easiest probably being int even = (notSureIfEven >> 1) << 1;. [I'm kind of assuming that with 'even' numbers you actually meant 'whole' numbers though, in which case you can ignore that.] Then if you don't want the range to be 0->X but Y->X you just add Y to your outcome (make sure to subtract Y from X before the multiplication or your range will be Y->X+Y).
To not generate the same number twice you can do different things. One way is to store all the numbers you generated so far in a List and then when you generate a new number, check if the list contains that number already, if so generate a new one until you got one that isn't in the list (and then when you do obviously add that to the list). Another way could be to preload all numbers it could generate into a list and then remove a random number out of that list.
Both ways probably won't scale very well to really large ranges of numbers though. The first one since it might get in a very long loop trying to find a number it hadn't generated yet, the second one because you'll have to create a really large list at the start.
I'm not sure if there's something you could do in the case of a really large range.

Random.nextInt(int) is [slightly] biased

Namely, it will never generate more than 16 even numbers in a row with some specific upperBound parameters:
Random random = new Random();
int c = 0;
int max = 17;
int upperBound = 18;
while (c <= max) {
int nextInt = random.nextInt(upperBound);
boolean even = nextInt % 2 == 0;
if (even) {
c++;
} else {
c = 0;
}
}
In this example the code will loop forever, while when upperBound is, for example, 16, it terminates quickly.
What can be the reason of this behavior? There are some notes in the method's javadoc, but I failed to understand them.
UPD1: The code seems to terminate with odd upper bounds, but may stuck with even ones
UPD2:
I modified the code to capture the statistics of c as suggested in the comments:
Random random = new Random();
int c = 0;
long trials = 1 << 58;
int max = 20;
int[] stat = new int[max + 1];
while (trials > 0) {
while (c <= max && trials > 0) {
int nextInt = random.nextInt(18);
boolean even = nextInt % 2 == 0;
if (even) {
c++;
} else {
stat[c] = stat[c] + 1;
c = 0;
}
trials--;
}
}
System.out.println(Arrays.toString(stat));
Now it tries to reach 20 evens in the row - to get better statistics, and the upperBound is still 18.
The results turned out to be more than surprising:
[16776448, 8386560, 4195328, 2104576, 1044736,
518144, 264704, 132096, 68864, 29952, 15104,
12032, 1792, 3072, 256, 512, 0, 256, 0, 0]
At first it decreases as expected by the factor of 2, but note the last line! Here it goes crazy and the captured statistics seem to be completely weird.
Here is a bar plot in log scale:
How c gets the value 17 256 times is yet another mystery
http://docs.oracle.com/javase/6/docs/api/java/util/Random.html:
An instance of this class is used to generate a stream of
pseudorandom numbers. The class uses a 48-bit seed, which is modified
using a linear congruential formula. (See Donald Knuth, The Art of
Computer Programming, Volume 3, Section 3.2.1.)
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. [...]
It is a pseudo-random number generator. This means that you are not actually rolling a dice but rather use a formula to calculate the next "random" value based on the current random value. To creat the illusion of randomisation a seed is used. The seed is the first value used with the formula to generate the random value.
Apparently javas random implementation (the "formula"), does not generate more than 16 even numbers in a row.
This behaviour is the reason why the seed is usually initialized with the time. Deepending on when you start your program you will get different results.
The benefits of this approach are that you can generate repeatable results. If you have a game generating "random" maps, you can remember the seed to regenerate the same map if you want to play it again, for instance.
For true random numbers some operating systems provide special devices that generate "randomness" from external events like mousemovements or network traffic. However i do not know how to tap into those with java.
From the Java doc for secureRandom:
Many SecureRandom implementations are in the form of a pseudo-random
number generator (PRNG), which means they use a deterministic
algorithm to produce a pseudo-random sequence from a true random seed.
Other implementations may produce true random numbers, and yet others
may use a combination of both techniques.
Note that secureRandom does NOT guarantee true random numbers either.
Why changing the seed does not help
Lets assume random numbers would only have the range 0-7.
Now we use the following formula to generate the next "random" number:
next = (current + 3) % 8
the sequence becomes 0 3 6 1 4 7 2 5.
If you now take the seed 3 all you do is to change the starting point.
In this simple implementation that only uses the previous value, every value may occur only once before the sequence wraps arround and starts again. Otherwise there would be an unreachable part.
E.g. imagine the sequence 0 3 6 1 3 4 7 2 5. The numbers 0,4,7,2 and 5 would never be generated more than once(deepending on the seed they might be generated never), since once the sequence loops 3,6,1,3,6,1,... .
Simplified pseudo random number generators can be thought of a permutation of all numbers in the range and you use the seed as a starting point. If they are more advanced you would have to replace the permutation with a list in which the same numbers might occur multiple times.
More complex generators can have an internal state, allowing the same number to occur several times in the sequence, since the state lets the generator know where to continue.
The implementation of Random uses a simple linear congruential formula. Such formulae have a natural periodicity and all sorts of non-random patterns in the sequence they generate.
What you are seeing is an artefact of one of these patterns ... nothing deliberate. It is not an example of bias. Rather it is an example of auto-correlation.
If you need better (more "random") numbers, then you need to use SecureRandom rather than Random.
And the answer to "why was it implemented that way is" ... performance. A call to Random.nextInt can be completed in tens or hundreds of clock cycles. A call to SecureRandom is likely to be at least 2 orders of magnitude slower, possibly more.
For portability, Java specifies that implementations must use the inferior LCG method for java.util.Random. This method is completely unacceptable for any serious use of random numbers like complex simulations or Monte Carlo methods. Use an add-on library with a better PRNG algorithm, like Marsaglia's MWC or KISS. Mersenne Twister and Lagged Fibonacci Generators are often OK as well.
I'm sure there are Java libraries for these algorithms. I have a C library with Java bindings if that will work for you: ojrandlib.

How to be sure that random numbers are unique and not duplicated?

I have a simple code which generates random numbers
SecureRandom random = new SecureRandom();
...
public int getRandomNumber(int maxValue) {
return random.nextInt(maxValue);
}
The method above is called about 10 times (not in a loop). I want to ensure that all the numbers are unique (assuming that maxValue > 1000).
Can I be sure that I will get unique numbers every time I call it? If not, how can I fix it?
EDIT: I may have said it vaguely. I wanted to avoid manual checks if I really got unique numbers so I was wondering if there is a better solution.
There are different ways of achieving this and which is more appropriate will depend on how many numbers you need to pick from how many.
If you are selecting a small number of random numbers from a large range of potential numbers, then you're probably best just storing previously chosen numbers in a set and "manually" checking for duplicates. Most of the time, you won't actually get a duplicate and the test will have practically zero cost in practical terms. It might sound inelegant, but it's not actually as bad as it sounds.
Some underlying random number generation algorithms don't produce duplicates at their "raw" level. So for example, an algorithm called a XORShift generator can effectively produce all of the numbers within a certain range, shuffled without duplicates. So you basically choose a random starting point in the sequence then just generate the next n numbers and you know there won't be duplicates. But you can't arbitrarily choose "max" in this case: it has to be the natural maximum of the generator in question.
If the range of possible numbers is small-ish but the number of numbers you need to pick is within a couple of orders of magnitude of that range, then you could treat this as a random selection problem. For example, to choose 100,000 numbers within the range 10,000,000 without duplicates, I can do this:
Let m be the number of random numbers I've chosen so far
For i = 1 to 10,000,000
Generate a random (floating point) number, r, in the range 0-1
If (r < (100,000-m)/(10,000,000-i)), then add i to the list and increment m
Shuffle the list, then pick numbers sequentially from the list as required
But obviously, there's only much point in choosing the latter option if you need to pick some reasonably large proportion of the overall range of numbers. For choosing 10 numbers in the range 1 to a billion, you would be generating a billion random numbers when by just checking for duplicates as you go, you'd be very unlikely to actually get a duplicate and would only have ended up generating 10 random numbers.
A random sequence does not mean that all values are unique. The sequence 1,1,1,1 is exactly as likely as the sequence 712,4,22,424.
In other words, if you want to be guaranteed a sequence of unique numbers, generate 10 of them at once, check for the uniqueness condition of your choice and store them, then pick a number from that list instead of generating a random number in your 10 places.
Every time you call Random#nextInt(int) you will get
a pseudorandom, uniformly distributed int value between 0 (inclusive)
and the specified value (exclusive).
If you want x unique numbers, keep getting new numbers until you have that many, then select your "random" number from that list. However, since you are filtering the numbers generated, they won't truly be random anymore.
For such a small number of possible values, a trivial implementation would be to put your 1000 integers in a list, and have a loop which, at each iteration, generates a random number between 0 and list.size(), pick the number stored at this index, and remove it from the list.
This is code is very efficient with the CPU at the cost of memory. Each potiental value cost sizeof(int) * maxValue. An unsigned integer will work up to 65535 as a max. long can be used at the cost of a lot of memory 2000 bytes for 1000 values of 16 bit integers.
The whole purpose of the array is to say have you used this value before or not 1 = yes
'anything else = no
'The while loop will keep generating random numbers until a unique value is found.
'after a good random value is found it marks it as used and then returns it.
'Be careful of the scope of variable a as if it goes out of scope your array could erased.
' I have used this in c and it works.
' may take a bit of brushing up to get it working in Java.
unsigned int a(1000);
public int getRandomNumber(int maxValue) {
unsigned int rand;
while(a(rand)==1) {
rand=random.nextInt(maxValue);
if (a(rand)!=1) { a(rand)=1; return rand;}
}
}

Probability in Java

I was curious to know, how do I implement probability in Java? For example, if the chances of a variable showing is 1/25, then how would I implement that? Or any other probability? Please point me in the general direction.
You'd use Random to generate a random number, then test it against a literal to match the probability you're trying to achieve.
So given:
boolean val = new Random().nextInt(25)==0;
val will have a 1/25 probability of being true (since nextInt() has an even probability of returning any number starting at 0 and up to, but not including, 25.)
You would of course have to import java.util.Random; as well.
As pointed out below, if you're getting more than one random number it'd be more efficient to reuse the Random object rather than recreating it all the time:
Random rand = new Random();
boolean val = rand.nextInt(25)==0;
..
boolean val2 = rand.nextInt(25)==0;
Generally you use a random number generator. Most of those return a number in the interval [0,1[ so you would then check whether that number is < 0.04 or not.
if( new Random().nextDouble() < 0.04 ) { //you might want to cache the Random instance
//we hit the 1/25 ( 4% ) case.
}
Or
if( Math.random() < 0.04 ) {
//we hit the 1/25 ( 4% ) case.
}
Note that there are multiple random number generators that have different properties, but for simple applications the Random class should be sufficient.
Edit: I changed the condition from <= to < because the upper boundary of the random number is exlusive, i.e. the largest returned value will still be < 1.0. Hence x <= 0.04 would actually be slightly more than a 4% chance, while x < 0.04 would be accurate (or as accurate as floating point math can be).
Since 1.7 it's better to use (in concurrent environment at least):
ThreadLocalRandom.current().nextInt(25) == 0
Javadoc
A random number generator isolated to the current thread. Like the global Random generator used by the Math class, a ThreadLocalRandom is initialized with an internally generated seed that may not otherwise be modified. When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention. Use of ThreadLocalRandom is particularly appropriate when multiple tasks (for example, each a ForkJoinTask) use random numbers in parallel in thread pools.
Usages of this class should typically be of the form: ThreadLocalRandom.current().nextX(...) (where X is Int, Long, etc). When all usages are of this form, it is never possible to accidently share a ThreadLocalRandom across multiple threads.
This class also provides additional commonly used bounded random generation methods.
Java has a class called java.util.Random which can generate random numbers. If you want something to happen with probability 1/25, simply generate a random number between 1 and 25 (or 0 and 24 inclusive) and check whether that number is equal to 1.
if(new java.util.Random().nextInt(25)==0){
//Do something.
}
Maybe you can implement this with generating random numbers.
Random rn = new Random();
double d = rn.nextDouble(); // random value in range 0.0 - 1.0
if(d<=0.04){
doSomeThing();
}

Categories