In this comment in another question, dimo414 states that one of the problems with the OP's code is that it will generate random numbers non-uniformly. So I wonder why this is? Is it inherent the the particular algorithm? Or is it something about Math.random() itself? Is it because of the floating-point representation of the numbers chosen in the interval [0.0, 1.0)?
p.s. I understand the proposed answer to use Random.nextInt(). I also want to know more about the flaws of using Math.random().
It has almost nothing to do with Math.random(). The OP's post says all that really needs to be said:
My issue is that on several different attempts, the last card in the
shuffled deck is consistently the same card as the last in the
unshuffled deck.
In other words, the shuffled deck has at least one card in common with the un-shuffled deck every time the code runs. That is most certainly deterministic, not random.
At least one problem with the OP's algorithm is that each iteration multiplies the random number by a smaller number than the previous iteration.
A better approach would have been to create a list of 52 random numbers. Then assign each card in the deck to each element in the list. Then sort the list by the random number and the result is the shuffled deck.
Java's Math.random() is documented to return numbers that "are chosen pseudorandomly with (approximately) uniform distribution from" the interval [0, 1). However, although that documentation specifies that it uses its own java.util.Random instance, it's not documented how it uses that instance to generate random numbers. For example, it's not documented whether that method will call the nextDouble method, which is exactly specified for java.util.Random.
Related
I'm new to using BigInteger, so I'm trying my best reading through the documentation for it. I'm still confused however. I need to generate 500 random integers between the range of 2^70 and 2^80 and I don't know how to set a range for BigIntegers.
I'm getting the possible duplicate messages, so I guess I should add that I've already looked at the solutions in this one and still don't understand how to solve my issue: How to generate a random BigInteger value in Java?
There is a built-in method to generate a random BigInteger between 0 and 2^n - 1.
You can use that in a loop to generate numbers up to 2^80.
The chance that a number will fall below 2^70 is very small ( ~ 0.1%). If that happens (and with 500 iterations it might very well), just draw another one.
This will give you a uniform distribution of random numbers between 2^70 and 2^80.
The chance that a number will repeat is almost nonexistent. If you feel that it cannot be ignored, check your previous numbers for duplicates, and draw again.
I have a program in which I need to generate random numbers that determine various outputs(To explain the exact reason would be too long). In theory a high number (lets say 100,000) is a valid output for my program, but its most likely(but not entirely impossible) going to end up being useless output.
I'd like to generate random numbers that are weighted to be around a "normalized" number.
For example I'd pick a number (10), and the majority of numbers that are randomly generated will be near 10. But there's a small chance the random number could any integer. I currently just use a range when generating the numbers, but this bothers me since numbers outside this range could potentially be valid and useful output.
Is there an easy way to do this without introducing to much overhead or having to map a percentage chances to individual integers?
For positive integers geometric, negative binomial, or Poisson are all possibilities. Java implementations are readily available for all of these.
I would consider this more of a statistics problem than a programming one. I think you want a logarithmic distribution. Here's an example Java implementation.
I am using a simple random calculations for a small range with 4 elements.
indexOfNext = new Random().nextInt(4); //randomize 0 to 3
When I attach the debugger I see that for the first 2-3 times every time the result is 1.
Is this the wrong method for a small range or I should implement another logic (detecting previous random result)?
NOTE: If this is just a coincidence, then using this method is the wrong way to go, right? If yes, can you suggest alternative method? Shuffle maybe? Ideally, the alternative method would have a way to check that next result is not the same as the previous result.
Don't create a new Random() each time, create one object and call it many times.
This is because you need one random generator and many numbers from its
random sequence, as opposed to having many random generators and getting
just the 1st numbers of the random sequences they generate.
You're abusing the random number generator by creating a new instance repeatedly. (This is due to the implementation setting a starting random number value that's a very deterministic function of your system clock time). This ruins the statistical properties of the generator.
You should create one instance, then call nextInt as you need numbers.
One thing you can do is hold onto the Random instance. It has to seed itself each time you instantiate it and if that seed is the same then it will generate the same random sequence each time.
Other options are converting to SecureRandom, but you definitely want to hold onto that random instance to get the best random number performance. You really only need SecureRandom is you are randomly generating things that have security implications. Like implementing crypto algorithms or working around such things.
"Random" doesn't mean "non-repeating", and you cannot judge randomness by short sequences. For example, imagine that you have 2 sequences of 1 and 0:
101010101010101010101010101010101
and
110100100001110100100011111010001
Which looks more random? Second one, of course. But when you take any short sequence of 3-4-5 numbers from it, such sequence will look less random than taken from the first one. This is well-known and researched paradox.
A pseudo-random number generator requires a seed to work. The seed is a bit array which size depends on the implementation. The initial seed for a Random can either be specified manually or automatically assigned.
Now there are several common ways of assigning a random seed. One of them is ++currentSeed, the other is current timestamp.
It is possible that java uses System.currentTimeMillis() to get the timestamp and initialize the seed with it. Since the resolution of the timestamp is at most a millisecond (it differs on some machines, WinXP AFAIK had 3ms) all Random instances instantiated in the same millisecond-resolution window will have the same seed.
Another feature of pseudo-random number generators is that if they have the same seed, they return the same numbers in the same order.
So if you get the first pseudo-random number returned by several Randoms initialized with the same seed you are bound to get the same number for a few times. And I suspect that's what's happening in your case.
It seems that the number 1 has a 30% chance of showing its self which is more than other numbers. You can read this link for more information on the subject.
You can also read up on Benford's law.
I am working on a project that needs to generate two random numbers from a given range (both of them at the same time, one after another) and check if they are equal to each other - if they are, proceed executing other code; if they aren't - generate the numbers again. Now my question is, if we have a range [0;10], and the first randomly generated number turned out to be 5, is the probability of the second number also being 5 as good as any other number? Specifically, does Math.random() have any "defense" against generating same number if it is called twice consecutively? or it "tries" to not generate the same number?
Generating the same number in the range [0,10] twice in succession is a perfectly valid occurrence for any random number generator. If it took any steps to prevent that it wouldn't be random.
On any invocation, the chances of any individual number being chosen should be 1:11, and each choice should be independent of previous choices, so the chances that in a pair the second number matches the first is 1 in 11.
As to how random Math.random() is, it's pseudo-random, meaning it uses an algorithm to generate a series of evenly distributed numbers starting with a "seed" value. It's not suitable for cryptography but quite good for simulations and other non-cryptographic uses.
When I need to shuffle a deck of poker cards in Java/Android, I use Collections.shuffle(List<?> list), of course. I've ever been doing this and the results seemed acceptable. But they aren't.
As outlined in this paper, there are 52! possible unique shuffles of a 52 card poker deck. That amounts to about 2^226.
But Collections.shuffle(List<?> list) uses new Random() by default which uses a 48-bit seed and can therefore only create 2^48 unique shuffles - which is only 3.49*10^(-52) percent of all possible shuffles!
So how do I shuffle cards the right way?
I've started using SecureRandom, but is that enough, finally?
List<Card> cards = new ArrayList<Card>();
...
SecureRandom secureRandom;
try {
secureRandom = SecureRandom.getInstance("SHA1PRNG");
}
catch (NoSuchAlgorithmException e) {
secureRandom = new SecureRandom();
}
secureRandom.nextBytes(new byte[20]); // force SecureRandom to seed itself
Collections.shuffle(cards, secureRandom);
You may only be able to get 248 different hands from a specific starting arrangement but there's no requirement that you start at the same arrangement each time.
Presumably, after the deck is finished (poker hands, blackjack and so on), it will be in an indeterminate order, and any one of those rearrangements will be suitable.
And, if you're worried about the fact that you start from a fixed arrangement each time you start your program, just persist the order when exiting and reload it next time.
In any case, 248 is still a huge number of possibilities (some 280,000,000,000,000), more than adequate for a card game, more so when you come to a realisation that it's limiting shuffles rather than arrangements. Unless you're a serious statistician or cryptographer, what you have should be fine.
Although you are using a SecureRandom, is still has a limited state. As long as that input seed has a smaller range than 52! it can not be completely random.
In fact, SHA1PRNG is 160 bit seeded, which means it is still not random enough. Follow this link, it has a solution years ago by using a third party library called UnCommons Math.
If you want real randomness, you could just skip pseudo random generators and go for something better like random numbers generated from athmospheric noise.
random.org offers an API to integrate random numbers generated that way into your own software.
Stealing an answer from the article you link:
START WITH FRESH DECK
GET RANDOM SEED
FOR CT = 1, WHILE CT <= 52, DO
X = RANDOM NUMBER BETWEEN CT AND 52 INCLUSIVE
SWAP DECK[CT] WITH DECK[X]
The random number generator should be good and use a 64 bit seed that you pick unpredictably, preferably using hardware.
How to really shuffle a deck?
There are several shuffling techniques.
Either (Stripping/Overhand):
Cut the deck in two
Add a small (pseudorandom) amount of one half to the front of the front of the other
Add a small (pseudorandom) amount of one half to the front of the back of the other
Do this until one hand is empty
Repeat
Or (Riffle):
Cut the deck in two
Set down a small (pseudorandom) portion of one half
Set down a small (pseudorandom) portion of the other
Do this until both hands are empty, and you have a new deck
Repeat
And there are more on top of this, as detailed in my link above.
Regardless, there are so many combinations that even the perfect shuffling algorithm would take a machine exploring 2*10^50 unique permutations per second to finish exploring every permutation in the time the universe has existed. Modern computers are only predicted to hit 1 ExaFLOPs (1*10^18 floating point operations per second) by 2019.
No human shuffler will explore that range of possibilities either, and you are, I believe (at the most basic level) simulating a human shuffling, correct? Would you find it likely that a croupier could shuffle an incrementally ordered deck into decreasing order in one shuffle? To split the deck with even ranks before odd, in one shuffle?
I don't find it unacceptable to limit yourself to a (albeit extremely) small subsection of that phase space (2^48 possible random numbers) in each shuffle, so long as you don't continuously seed the same way etc.
There are exactly 52 factorial (expressed in shorthand as 52!) possible orderings of the cards in a 52-card deck. This is approximately 8×1067 possible orderings or specifically: 80,658,175,170,943,878,571,660,636,856,403,766,975,289,505,440,883,277,824,000,000,000,000.
The magnitude of this number means that it is exceedingly improbable that two randomly selected, truly randomized decks, will ever, even in the history of the Universe, be the same. However, while the exact sequence of all cards in a randomized deck is unpredictable, it may be possible to make some probabilistic predictions about a deck that is not sufficiently randomized.
~Wikipedia
Also, it's worth noting that Bayer & Diaconis in 1992 proved it only takes 7 good shuffles to properly randomize a deck, here is the section on it from wikipedia which has plenty links to papers discussing this.