Coin toss using random numbers does not appear exactly random - java

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.

Related

How to use MersenneTwisterRNG random number generator

I am trying to implement a random number generator in my Java program. I was using Math.random() but that didn't seem to work very well. Then I tried using SecureRandom, but that took too long for my game. However, I came across this generator, the MersenneTwisterRNG random number generator. It seems to be what I want; fast, but still random.
However, I have not been writing in Java for very long, only 2 months, and I cannot make heads nor tails of the API. If anyone could help explain to me how to use this in my code, it would be appreciated. Or, if you happen to know of a simpler, but similar, random number generator, I would be interested in that as well. The API is here.
How to use the MersenneTwisterRNG API:
import java.util.Random;
import org.uncommons.maths.random.MersenneTwisterRNG;
This lets you access the classes using their short names.
Random rand = new MersenneTwisterRNG();
This creates a new MersenneTwisterRNG. We put it into a variable of type Random so that we can swap it out for another RNG easily if needed.
double x = rand.nextDouble();
This behaves the same as Math.random(), and returns a double-precision floating-point number between 0.0 and 1.0.
int n = rand.nextInt(10);
This generates a random number between 0 (inclusive) and 9 (inclusive), i.e. 0 <= n < 10. This is useful for a lot of integer algorithms.

Select one of three numbers with equal probability?

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
}

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.

Finding a prime number at least a 100 digits long that contains 273042282802155991

I am new to Java and one of my class assignments is to find a prime number at least 100 digits long that contains the numbers 273042282802155991.
I have this so far but when I compile it and run it it seems to be in a continuous loop.
I'm not sure if I've done something wrong.
public static void main(String[] args) {
BigInteger y = BigInteger.valueOf(304877713615599127L);
System.out.println(RandomPrime(y));
}
public static BigInteger RandomPrime(BigInteger x)
{
BigInteger i;
for (i = BigInteger.valueOf(2); i.compareTo(x)<0; i.add(i)) {
if ((x.remainder(i).equals(BigInteger.ZERO))) {
x.divide(i).equals(x);
i.subtract(i);
}
}
return i;
}
Since this is homework ...
There is a method on BigInteger that tests for primality. This is much much faster than attempting to factorize a number. (If you take an approach that involves attempting to factorize 100 digit numbers you will fail. Factorization is believed to be an NP-complete problem. Certainly, there is no known polynomial time solution.)
The question is asking for a prime number that contains a given sequence of digits when it is represented as a sequence of decimal digits.
The approach of generating "random" primes and then testing if they contain those digits is infeasible. (Some simple high-school maths tells you that the probability that a randomly generated 100 digit number contains a given 18 digit sequence is ... 82 / 1018. And you haven't tested for primality yet ...
But there's another way to do it ... think about it!
Only start writing code once you've figured out in your head how your algorithm will work, and done the mental estimates to confirm that it will give an answer in a reasonable length of time.
When I say infeasible, I mean infeasible for you. Given a large enough number of computers, enough time and some high-powered mathematics, it may be possible to do some of these things. Thus, technically they may be computationally feasible. But they are not feasible as a homework exercise. I'm sure that the point of this exercise is to get you to think about how to do this the smart way ...
One tip is that these statements do nothing:
x.divide(i).equals(x);
i.subtract(i);
Same with part of your for loop:
i.add(i)
They don't modify the instances themselves, but return new values - values that you're failing to check and do anything with. BigIntegers are "immutable". They can't be changed - but they can be operated upon and return new values.
If you actually wanted to do something like this, you would have to do:
i = i.add(i);
Also, why would you subtract i from i? Wouldn't you always expect this to be 0?
You need to implement/use miller-rabin algorithm
Handbook of Applied Cryptography
chapter 4.24
http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf

Categories