• Post Reply Bookmark Topic Watch Topic
  • New Topic

Problem generating random numbers  RSS feed

 
Ranch Hand
Posts: 376
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Running  the program is printing large numbers of repeated values:
...
i=1 j=0 nextVariable=6 count=738377
i=1 j=0 nextVariable=6 count=738378
i=1 j=0 nextVariable=6 count=738379
i=1 j=0 nextVariable=6 count=738380
i=1 j=0 nextVariable=6 count=738381
i=1 j=0 nextVariable=6 count=738382
i=1 j=0 nextVariable=6 count=738383
i=1 j=0 nextVariable=6 count=738384
i=1 j=0 nextVariable=6 count=738385
i=1 j=0 nextVariable=6 count=738386
i=1 j=0 nextVariable=6 count=738387
i=1 j=0 nextVariable=6 count=738388
i=1 j=0 nextVariable=6 count=738389
i=1 j=0 nextVariable=6 count=738390

I have also tried with

...
i=2 j=1 nextVariable=9 count=201758
i=2 j=1 nextVariable=9 count=201759
i=2 j=0 nextVariable=5 count=201760
i=2 j=1 nextVariable=9 count=201761
i=2 j=1 nextVariable=9 count=201762
i=2 j=1 nextVariable=9 count=201763
i=2 j=1 nextVariable=9 count=201764
i=2 j=0 nextVariable=5 count=201765
i=2 j=1 nextVariable=9 count=201766
i=2 j=1 nextVariable=9 count=201767
i=2 j=1 nextVariable=9 count=201768
i=2 j=1 nextVariable=9 count=201769
i=2 j=0 nextVariable=5 count=201770

I had similar problems with java.util.Random. Is my computer the problem?

 
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, that is pretty incomprehensible code, partially because the method is too long. Please go through it and explain what each part is supposed to do. Also what is the whole method supposed to do?
What does nextInt(0, 1 + 1) mean? What does it mean about repeated literal? Why are yo uusing the term literal when that array doesn't contain number literals?
Don't us 3 in the continuation part of a for loop; use myArray.length instead.
Why are you setting that boolean to true (line 20) and not setting it to false? How do you think your loop is going to terminate?
 
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'll echo Campbell here.
What is it you are trying to do with this code?

In addition, what is the value of "variables" for your typical run, more out of curiosity.

And as he says, the loop will never end once you get a match.
As for why you get these long runs, let's take your first example data.

i=1 j=0 nextVariable=6 count=738377
i=1 j=0 nextVariable=6 count=738378
i=1 j=0 nextVariable=6 count=738379
i=1 j=0 nextVariable=6 count=738380

Now, clearly when i = 0 the value of literals[0] was set to 6.
The next time round the random number generator generated a 6 again (this can happen), meaning that the repeatedLiteral flag is set true.

Now, the do..while loop will never end, and whenever the random number generator generates a '6' it will produce an output line.  Every other time it doesn't (so you never see them).

For the second run, the "hit" didn't occur until the third time round the 'i' loop, so you had two number in the literals array (a 5 and a 9), so the same thing happened, but it now had two numbers it could match.
 
Alejandro Barrero
Ranch Hand
Posts: 376
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you very much for your help. The commented code is

The program works correctly if the code that tests for repeated values is commented

To run the code I am using

I will be very happy to provide any further clarification.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So you want an array of size 3 containing unique numbers between the range 1 to "variables"?
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Those comments, I am afraid, are not much good. We can see that you are creating three random numbers in line 6, but the comments don't tell us what you are trying to do overall.
Why are you making the numbers negative before testing for duplicates? If you test for duplicates first, you won't need to use Math#abs().
Why have you got the strange syntax 1 + 1? Why not write 2? I can see another way to get a 50/50 probability:-
number = Math.random() < 0.5 ? number : -number;
That is one of the few places I can think of where Math.random() is easier to use than a Random object.

You are not putting random numbers into your array (not even pseudo‑random); what you want is called random selection from a declining population. There are several ways to get that. One is to collect the numbers into a List ad remove elements repeatedly at random indices. Another way would be to use a Stream, in the following code an IntStream. You can get an IntStream from the #ints() method, and remove duplicates with one of its methods. That will become expensive on memory and processor time if the size of result approaches the range of the stream; if you want twenty numbers in the range 1...20, you may have a long wait to get the last number. If you take three numbers from a large range, that will probably not be a serious problem. Since you only want three numbers, you can use another method to limit the size, and the intent of the last method call will doubtless be obvious from its name.Note that will not produce a result of 20, only up to 19.
There is an easy way to get negative numbers: change the code to read like this (i must be positive):-That array might contain −20. That is much better than trying to make numbers negative after the event:-I shall leave you to work out what line 3 means; this Java™ Tutorials section will be helpful. Also to work out why line 3 isn't necessarily the best way to do it. You can change that line to
....map(i -> myArrayrandom.nextInt(2) == 0 ? i : -i)...
or similar.

[edit]Did I really write myArray? That shou‍ld read random.
 
Alejandro Barrero
Ranch Hand
Posts: 376
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I respectfully disagree. You do say "We can see that you are creating three random numbers in line 6, but the comments don't tell us what you are trying to do overall." What I am trying to do overall is inmaterial, although the comment says clealy that I want to create an array of three int with absolute value from one to maximum.
You also say; "Why are you making the numbers negative before testing for duplicates? If you test for duplicates first, you won't need to use Math#abs()" I am making some of the numbers negative because I want to have the numbers negative with a 50% of probability. Yes, I could create three numbers at random and verify that they are not repeated; then I could loop over the array and change the numbers to negative with 50% probabilkty, but that is a waste of time. "Why have you got the strange syntax 1 + 1?" I am wrtimng 1 + 1 because anybody who anderstands the code of ThreadLocalRandom.current().nextInt() knows that the arguments are minimum, maximum + 1.
When you say "You are not putting random numbers into your array (not even pseudo-random)", you should know know that you cannot create random numbers in a computer (you need a physical process for tha;, you would know that you are wrong if you understood ThreadLocalRandom.current().nextInt() (it returns pseudo-random numbers).
I don't want to use streams and that's my choice; I am not asking for help to make my code better; I am asking for help to fing out why the random number generator is not working. At this point I am considering writing a method using The Linear Congruential Method from the book "The Art of Computing Programming volume I Fundamental Algorithms" by professor Donal E Knuth; I will post the results when I am done.
 
Sheriff
Posts: 22845
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alejandro Barrero wrote:I am asking for help to fing out why the random number generator is not working.


And yet, even though you have been asked to do so, you haven't said what that code is supposed to do. So all we know is that it doesn't do what it is supposed to do, whatever that is. It's pretty hard to figure out what's wrong with code when you don't know its purpose.
 
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm coming to this party a little late, but here are some observations. What you intend to do with this method is immaterial but describing the requirements for the method so that another developer could go off and write it, is important.

I'm having trouble understanding your code so instead I took a shot at writing one myself with the best understanding of the requirements I could get from this thread. I think my code may be a bit easier to understand than yours but I'm not sure I'm on the mark with your requirements. Please tweak the requirements if I've gotten it wrong.

 
Alejandro Barrero
Ranch Hand
Posts: 376
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks to Carey Brown. I changed the code in two simple ways

I am using the code to generate 20 arrays.


It is necessary to compare absolute values.

I only got three repetitions in three different arrays.
[1, -3, -2]
[-2, -9, 1]
[10, 2, 6]
qtyFilled=2 i=1 lookFor-4 count=0qtyFilled=2 i=0 lookFor7 count=0[-7, 4, -6]
[1, -4, -7]
[9, 7, -4]
[8, -2, -3]
[1, -3, 5]
[-2, -8, -6]
[-1, 4, 8]
qtyFilled=1 i=0 lookFor2 count=0[-2, 4, 8]
[9, -7, -5]
[-1, 4, 10]
[8, 4, 6]
[4, 5, -1]
[7, -9, -2]
qtyFilled=2 i=0 lookFor-1 count=0[-1, 3, 4]
[10, 3, 4]
[-7, 2, 5]
[-4, 9, 3]

Wonderful. The good news is that now I know how to do it; The bad news is that after so many analysis I still don't know what I was doing wrong; by to morrow I'll figure out my stupidity. Great thanks Carey Brown.
 
Carey Brown
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alejandro Barrero wrote:

Two minor nits. Your count variable never changes (probably don't need count at all). Change print() to println() and you'll see that 4 were rejected, not 3.
 
Carey Brown
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're welcome.

One of the things I hope you take away from this is that you need to take your big problem and break it into smaller pieces that have a clear scope, like inArray() and nextRandom(). It is easier to make small methods to do these tasks and you eliminate having to write loops nested four deep in your main method(), which adds complexity that can quickly get out of control.
 
Paul Clapham
Sheriff
Posts: 22845
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's horribly complicated if you have to use arrays, isn't it? How about



 
Carey Brown
Saloon Keeper
Posts: 3329
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The OP hasn't gotten to enhanced for() loops yet so I'm guessing he hasn't gotten to Collections either. But, yes, Sets would be a good way to deal with this. I've tweaked your code to fit the requirements. I'm not sure why the OP chose ThreadLocalRandom but the use of Math.random() may be in conflict with this requirement (?).
 
Paul Clapham
Sheriff
Posts: 22845
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Carey Brown wrote:The OP hasn't gotten to enhanced for() loops yet...


That could be true, but nothing about that has been said in this thread yet.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alejandro Barrero wrote:
Wonderful. The good news is that now I know how to do it; The bad news is that after so many analysis I still don't know what I was doing wrong; by to morrow I'll figure out my stupidity. Great thanks Carey Brown.


I though I explained what was happening with your original code.
You were misinterpreting the output as being "not random", whereas it was simply an artifact of the way you were logging things, and the fact that you had no exit from your while loop.

Your original code (assuming I understood what the method was trying to achieve) could have been "fixed" with something like:

where the getRandomNumber() method produces the random number (covering lines 9-14 in your original code) and isDuplicate() does the check covered by lines 15-22.
You'd have to provide suitable parameters for these new methods, and the code won't be straight copy/paste from your original, but that's the structure I'd expect to see, at least as a first pass fix.
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alejandro Barrero wrote:. . . "We can see that you are creating three random numbers in line 6, but the comments don't tell us what you are trying to do overall."
I wasn't clear; that makes the comment useless. It is a waste of time to write comments which only tell us what we can see already.
What I am trying to do overall is inmaterial. . .
That isn't true. Because you didn't say what you are trying to do, we don't know whether what you are writing helps or hinders.
I want to have the numbers negative with a 50% of probability.
And how do you know what you have is mathematically correct? I think you are introducing a bias into the process. I think you are causing one value to appear with a greater frequency than all other values. And I think you will not have 50% of your numbers negative. The bias may be slight, but it is real.
. . . I am wrtimng 1 + 1 because anybody who anderstands the code of ThreadLocalRandom.current().nextInt() knows that the arguments are minimum, maximum + 1.
No, they are startInclusive, endExclusive. You shou‍ld use 0, 2. Using 1 + 1 simply makes your code harder to read.
When you say "You are not putting random numbers into your array (not even pseudo-random)", you should know know that you cannot create random numbers in a computer . . .
Of course I know that. I also know that random numbers entail the possibility of duplicates, so you are not writing random numbers in the first place. You are writing something different.
 
Master Rancher
Posts: 2045
75
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:(...) I also know that random numbers entail the possibility of duplicates, so you are not writing random numbers in the first place. You are writing something different.

Compare it to drawing without replacement. What is not random about that?
 
Alejandro Barrero
Ranch Hand
Posts: 376
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I still don't understand why my old code was generating a huge number of duplicate random numbers


New code with an idea from Carey Brown works like a charm.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because you never exit the do...while loop, so it constantly generates new numbers.

I'll step through your first example in your original post.

1. Enter the for loop (i = 0)

2. Enter the do while loop

3. Get a random number, in this case 6 (the toss is irrelevant here, as your comparisons are all with the positive value).

4. Since i == 0 then there is no check done, and literals[0] is set to 6.

5. Exit the do while loop as repeatedLiteral is false, and back round the for loop, so i = 1 now.

6. Get a new random number, again (as it has a 1 in 10 chance of happening) this is a 6.

7. The check for duplicates comes back true, so repeatedLiteral becomes true.

8. literals[1] is set to 6 (this is actually irrelevant to the problem).

9. Back round the do while loop (repeatedLiteral is true now).

10. Get a random number...let's say 10 (it doesn't matter unless it's a 6).

11. literals[1] is now set to 10.

12.  And...back round the do while loop as repeatedLiteral is still true.

13.  Repeat steps 10 through 12 however many times (we cannot exit), with step 10 producing a number between 1 and 10.

Now...whenever step 13 generates a 6 it will print out a log line (and increment count).
Because you only log when nextVariable is 6 (the matching number) you never see the other values that are being generated.
It's generating a huge number of the same number because what else would you expect when you roll a 10 sided dice a million times?

That's your issue with your original code.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!