0

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().

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • 2
    The Javadoc says "... _Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range._ ..." – Dawood ibn Kareem Jul 02 '17 at 20:12
  • Could you repeat the parts of the original question that you think are relevant? Right now, you are kind of only asking to comment on the original issue -- i.e. difficult to treat as an individual question if the original question would disappear. – jsalonen Jul 02 '17 at 20:12
  • 3
    This is discussed in detail [in this question](https://stackoverflow.com/q/738629/113632). The underlying issue is that the possible values returned from `Math.random()` do not correspond 1:1 with most discrete ranges. In general it is easy to introduce bias or skew when attempting to transform a random variable. Best left to the experts. – dimo414 Jul 02 '17 at 20:16
  • 1
    The difference between the two approaches is minuscule and absolutely not worth worrying about in any real-world application. – Dawood ibn Kareem Jul 02 '17 at 20:21
  • @DawoodibnKareem That is my assessment as well. The real issue is that the OP is erroneously subtracting 1 from the size of the list. – Code-Apprentice Jul 03 '17 at 09:01

2 Answers2

0

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.

Yahya
  • 13,349
  • 6
  • 30
  • 42
Jeff Holt
  • 2,940
  • 3
  • 22
  • 29
  • No, sorting by randomness is less efficient than using a **valid** shuffling algorithm such as [Fisher-Yates](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle) or the builtin [`Collections.shuffle`](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#shuffle-java.util.List-). – pjs Jul 02 '17 at 21:07
  • @pjs Perhaps it is but the use case is an 52 element array and the OP is more interested in learning the deficiencies of something that does not work at all. If the OP were looking for the best code to reuse, then Collections.shuffle might be ideal. – Jeff Holt Jul 02 '17 at 21:10
  • "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." This "one problem" is almost certainly inefficient but not incorrect. I mean that the bug the OP is asking about is caused by an arithmetic error in the implementation, not in the algorithm itself. – Code-Apprentice Jul 02 '17 at 21:30
  • "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." I believe this is because of an error in implementation. The OP subtracts 1 from the size, and therefore, the last element of the original list will never be chosen until the very last iteration. – Code-Apprentice Jul 03 '17 at 09:03
0

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.

Peter O.
  • 32,158
  • 14
  • 82
  • 96