Author Topic: Bad random numbers, or TIMER limitation...?  (Read 7758 times)

0 Members and 1 Guest are viewing this topic.

Offline Statsman1

  • Newbie
  • Posts: 36
  • I'm just a jerk, but a hero is what I want to be.
    • View Profile
Bad random numbers, or TIMER limitation...?
« on: October 25, 2021, 08:18:02 pm »
Hey guys...

Picture 6 horses in a race, using the TIMER function at the START and FINISH to calculate elapsed time.  They finish with the following times (in seconds)...

Racer 1    31.30453     
Racer 2    31.48992     
Racer 3    31.50592     
Racer 4    31.8607     
Racer 5    32.23148     
Racer 6    32.41687

Then picture 6 different horses in a race, but same distance as race 1.  This time, the results (in seconds) are...

Racer 7    30.93375     
Racer 8    30.94975     
Racer 9    31.11914     
Racer 10  31.30453     
Racer 11  31.48992     
Racer 12  31.50592

Note that Racer 11 and Racer 12 have EXACTLY the same times as Racer 2 and Racer 3.  The fact that all 6 times are not the same is encouraging, but how on earth could two identical times be possible, let alone have it happen twice?

I have seen this happen over a series of races...duplicate times (but not duplicate places in finish) come up a LOT.  For instance, the time 32.77441 has happened 6 times in 30 races.  That just doesn't seem to be right.

I have used the RANDOMIZE (-TIMER) and RANDOMIZE (TIMER) functions within the program - the first is used to determine how far forward the horse moves (the maximum is 3 pixels, the minimum is 1 pixel, so in practice, thus the average is 2 pixels).   The second is invoked after every horse has moved, to calculate a random-length system delay between each move.  To me, this means a new seed is generated every single time the program accesses the routine used to create the delay, I then take the average of 100 random numbers, and use this as the delay..maybe I misunderstand this function.

        Randomize (Timer)
        L = 0
        For J = 1 To 100
            K = Rnd(1) / 1000
            L = L + K
        Next J

        m = L / 10

        _Delay (m)

Anyway, I get that over running a series of random numbers between 1 and 3 will average 2, and that if you do that constantly over the same distance, you will get very similar times to complete the race...but introducing that random delay should be enough to avoid timing duplication down to the 100,000th of a second, shouldn't it?


Good decisions come from experience.
Experience comes from bad decisions.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #1 on: October 25, 2021, 08:52:00 pm »
I think if you don't Randomize Timer, you will have to go through a million numbers or so before repeats. I'd do it once at the beginning after you have your program debugged so that your starts are always different. RND uses a formula and patterns will show up according to formula.

I've taken all the points on the screen shuffled them and drew them before recyling another set of points. That covers the screen once before repeats. You could do same with race times!

Offline Statsman1

  • Newbie
  • Posts: 36
  • I'm just a jerk, but a hero is what I want to be.
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #2 on: October 25, 2021, 09:01:52 pm »
Thanks bplus...

I use RANDOMIZE (-TIMER) at the very start of my program, and it is called only once.

Are you saying I shouldn't bother with the second RANDOMIZE (TIMER)?  Or is there just a better way to pick a random number? 

All I am doing is trying to figure out how the heck two separate events can time exactly the same to the 5th decimal point when everything that contributes to that time is a series of apparently random numbers.
Good decisions come from experience.
Experience comes from bad decisions.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #3 on: October 25, 2021, 09:06:24 pm »
Yes, I don't think you will see repeat number unless you reseed RANDOMIZE often.

Try getting repeat with Randomize Timer only at start, only once.

PS I am wondering why you are putting Timer in parenthesis and about -Timer, I suppose it's OK? just strikes me as odd.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #4 on: October 25, 2021, 09:15:45 pm »
No repeats for 10,000
Code: QB64: [Select]
  1. Dim r(1 To 10000)
  2. For i = 1 To 10000
  3.     r(i) = Rnd
  4.     For j = 1 To i - 1
  5.         If r(i) = r(j) Then Beep: repeats = repeats + 1
  6.     Next
  7. Print "Repeats = "; repeats
  8.  
  9.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #5 on: October 25, 2021, 09:20:13 pm »
I am running 100,000 been quiet except for CPU ;-))

I think you have to go to 1,000,000 to start getting repeats.

!00,000 done no repeats.

Offline Statsman1

  • Newbie
  • Posts: 36
  • I'm just a jerk, but a hero is what I want to be.
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #6 on: October 25, 2021, 09:27:57 pm »
So I just have RANDOMIZE (TIMER) at the start, no other occurrences of a randomize.

These are the sorted times of 10 races, 6 racers in each...still a ton of duplications.

45.81797
46.00336
46.00336
46.00336
46.01936
46.01936
46.18875
46.37414
46.37414
46.55953
46.74492
46.77141
46.78741
46.93031
46.93031
46.9568
47.1157
47.1157
47.1157
47.1317
47.1317
47.30109
47.30109
47.48648
47.67188
47.68787
47.88375
47.88375
47.88375
47.89975
47.89975
48.25453
48.41344
48.41344
48.42944
48.43992
48.59883
48.59883
48.78422
48.96961
48.96961
48.96961
49.34039
49.52578
49.73766
50.08195
50.47922
50.66461
50.85
51.03539
51.59156
51.77695
51.96235
Good decisions come from experience.
Experience comes from bad decisions.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #7 on: October 25, 2021, 11:28:31 pm »
That's weird have to see code that generates numbers I guess.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #8 on: October 25, 2021, 11:44:14 pm »
Here's another test sorting the 10,000 items:
Code: QB64: [Select]
  1. Dim Shared sa(1 To 10000)
  2. For i = 1 To 10000
  3.     sa(i) = 100 * Rnd
  4. QSort 1, 10000
  5. For i = 1 To 10000
  6.     Print sa(i)
  7.     If i Mod 20 = 0 Then Sleep: Cls
  8.     If i > 1 Then
  9.         If sa(i) = sa(i - 1) Then Beep: repeats = repeats + 1
  10.     End If
  11. Print "Repeats"; repeats
  12.  
  13. Sub QSort (Start, Finish) 'sa needs to be   DIM SHARED !!!!     array
  14.     Dim i As Long, j As Long, x$
  15.     i = Start
  16.     j = Finish
  17.     x = sa(Int((i + j) / 2))
  18.     While i <= j
  19.         While sa(i) < x
  20.             i = i + 1
  21.         Wend
  22.         While sa(j) > x
  23.             j = j - 1
  24.         Wend
  25.         If i <= j Then
  26.             Swap sa(i), sa(j)
  27.             i = i + 1
  28.             j = j - 1
  29.         End If
  30.     Wend
  31.     If j > Start Then QSort Start, j
  32.     If i < Finish Then QSort i, Finish
  33.  
  34.  

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Bad random numbers, or TIMER limitation...?
« Reply #9 on: October 26, 2021, 01:25:43 am »
        Randomize (Timer)
        L = 0
        For J = 1 To 100
            K = Rnd(1) / 1000
            L = L + K
        Next J

        m = L / 10

        _Delay (m)


There's so much strange stuff going on above, I have no idea where to even start diagnosing it...

        For J = 1 To 100
            K = Rnd(1) / 1000
            L = L + K
        Next J

First, why do we need to get 100 different random numbers between 0 and 0.9999999?  Just for the value of L?  At 100 rolls, you're going to hit mighty damn close to the average of 0.5 overall.  100 rolls * average value of 0.5 = 50.  Of course, you /1000 each time, so L is going to be close to 0.05. 

I'm willingto bet a cookie that L never varies more than 0.002 from 0.05.  I'll bet a box of cookies that it never varies more than 0.005 from that average.

But then m is L / 10, which makes it ~0.005....

Which then introduces an incredibly small delay into the code...

Which is for, "introducing that random delay should be enough to avoid timing duplication down to the 100,000th of a second..."

???

It sounds to me like all this is inside a main loop and you're trying to move your randomizer seed manually each pass, but that 0.005 second delay isn't changing the seed but by a miniscule value, letting you generate the same repetitive values over and over...

Fix for this? 

Drop the FOR loop, and the _DELAY completely. 

RND works off a formula.  A delay doesn't do anything to it, but in this case your use of RANDOMIZE TIMER repeatedly in a short timeframe is keeping your seed value close to the same entry point in the RND formulas.

Move RANDOMIZER TIMER outside all your other loops.  Run it once when the program starts and be done with it.  After that, basically strip out all you have and stick with a simple bit below in your main loop.

K = RND
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Statsman1

  • Newbie
  • Posts: 36
  • I'm just a jerk, but a hero is what I want to be.
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #10 on: October 26, 2021, 10:05:26 am »
Thank you, Steve, for the insight here.  I have removed the second RANDOMIZE and only triggering one RANDOMIZE (TIMER) at the beginning of the program.  The goal of that 100-loop accumulation was simply to introduce a random delay on each sweep of the code that determines movement of the horses, because I am consistently getting identical times, which is really what I am asking about.

I agree 100 percent that the mean of a series of random numbers between 0 and .999999 approaches .5, and that loop wasn’t doing much, except that probably WASN’T exactly .5, and because _DELAY can use 1/1000ths, it should have been enough to prevent the identical times (to the 1/100000th) happening.  It wasn’t.

I am not the most optimized coder, no question about that, but when I time events using TIMER, with that precision, I still cannot figure out how I am getting identical times all the way to the 1/100000th of a second.  That should be, to my mind, quite impossible….or, since anything is possible, FAR less frequent.

There is too much code to paste here, but the gist of it is….

BEGIN
START RACE
StartTime = TIMER
Race is 1,440 pixels long
Begin Loop
Random numbers between 1 and 3 determine how many pixels forward each horse moves
All 6 horses move, in random order
All horses move forward
Eventually, each horse has moved 1,440 pixels (enough passes of 1, 2 or 3 have happened to add up to 1,440)
First horse crosses finish line
FirstTime = TIMER
FirstTime = FirstFinish - StartTime
Second horse crosses finish line
SecondFinish = TIMER
SecondTime = SecondFinish - TIMER
.
.
.
Sixth horse crosses finish line
SixthFinish = TIMER
SixthTime = SixthFinish - StartTime
End of loop
Race is done - display results
END

Sometimes, there are EXACT ties in a race.  Dead heats happen in horse races, I have no issue with that, though, again, a tie to the 1/100000th of a second seems kind of wildly unlikely.

But run a few of these, and I get some identical times, all the way down to the 1/100000 of a second (I posted a list of 10 races x 6 times).  The 4th place finisher in race #6 will have the identical time to the 2nd place finisher in race #3, for example.  Again, to the 1/100000th of a second.  That just should NOT happen. 

I tried this.  If I run a race where all horses move 3 pixels at a time, all 6 finish at basically the same time, but the first horse to move that last cycle wins by 2/100th of a second.  Makes sense, there is processing time being used.  However, all the other 5 horses have the exact same time down to the 5th decimal place.  Something is strange about this type of thing.
Good decisions come from experience.
Experience comes from bad decisions.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #11 on: October 26, 2021, 11:57:29 am »
Here's your horse race man.
Code: QB64: [Select]
  1. Width 120
  2. Const track = 100
  3. Dim horses(1 To 6)
  4. Dim loops(1 To 6)
  5. Dim stillRunning, i
  6.  
  7. stillRunning = 1
  8. While stillRunning = 1
  9.     stillRunning = 0 ' clear flag
  10.     For i = 1 To 6
  11.         If horses(i) <= track Then
  12.             loops(i) = loops(i) + 1
  13.             stillRunning = 1 'set flag
  14.             horses(i) = horses(i) + Rnd * .25
  15.         End If
  16.     Next
  17.     Cls
  18.     Print
  19.     For i = 1 To 6
  20.         Color i
  21.         Print Tab(Int(horses(i))); horses(i)
  22.         Print
  23.     Next
  24.     Color 15
  25.     Locate 1, 1
  26.     For i = 1 To 6
  27.         Print Tab(100); "|"
  28.         Print
  29.     Next
  30.     _Limit 60
  31. Print "And the results are in:"
  32. For i = 1 To 6
  33.     Color i
  34.     Print i, loops(i)
  35.  

And yes you will get allot of repeat "times" because the average of a bunch of random numbers condenses around an average. You can even see about what the average is by the distribution of "times".

Notice I did not use timer but just counted how many "steps" it took each horse to get past the end of the track


Offline Statsman1

  • Newbie
  • Posts: 36
  • I'm just a jerk, but a hero is what I want to be.
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #12 on: October 26, 2021, 01:34:07 pm »
Hey bplus!

Thanks for this, and yes, I know that the averages condense to a single value (for instance, the average of random numbers between 1 and 3 will end up narrowing down to 2).  My issue is that the TIMER function spits out exactly the same times to the 1/100000th of a second over a small sample size of events.

I have done the same thing you did…I count the number of loops it takes to finish a race (because I thought that was the cause) and the number of loops is almost always different.  Here, 11 races in question took the following number of loops to finish…

600, 610, 613, 604, 603, 609, 611, 619, 596, 604, 612

The average of that is 607, which actually never happened in those races.

So if a race that took 613 loops produced a 2nd place finish in 34.123456 seconds, how on earth did another race that took 596 loops have a 4th place finisher in 34.123456 seconds as well? 

The fact that those two events use TIMER to achieve the EXACT SAME TIME is my issue.  Not the random numbers generated to do it.

Maybe I am the only guy who thinks that two things that time to that level of identical accuracy is odd.
Good decisions come from experience.
Experience comes from bad decisions.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #13 on: October 26, 2021, 02:07:06 pm »
Hi Statsman1

I set up a different view of horse racing. Here I start off favoring each horse with increasing probabilities for winning or being faster whatever you want to call it the higher the horse number the more likely it would win but only by small fraction.

It takes 1000 races to see the order of horses and 10,000 to confirm the order for sure!
Code: QB64: [Select]
  1. _Title "Horse Race #2" 'b+ 2021-10-26
  2.  
  3. ' I want to split the odds evenly between 6 horses but I don't want the 2nd worse horse be twice as likely to win as worse
  4. ' the 3rd worse.
  5.  
  6. 'The sum of 1 + 2+ 3.. + 6 = 6(7)/2 = 21
  7. 'so give each horse 21 + n/21 = 6 * 21 + 21 = 126 + 21 = 147
  8. ' or (21 + n/21)/147
  9. Dim pHorse(1 To 6)
  10. 'check that adds to 1.0
  11. For i = 1 To 6
  12.     pHorse(i) = (21 + i) / 147
  13.     total = total + pHorse(i)
  14.     If i = 1 Then Print i, pHorse(i)
  15.     If i > 1 Then Print i, pHorse(i), pHorse(i) - pHorse(i - 1)
  16. Print "Total p ="; total
  17.  
  18. ' that looks like a horse race, in the short run any horse can win in the long haul the better horses will win more orderly
  19. Dim races(1 To 6), nRaces
  20. nRaces = 10
  21.  
  22. moreRaces:
  23. For race = 1 To nRaces
  24.     ' A race
  25.     Cls
  26.     Print "A day at the Races, and any horse can win!"
  27.     Print "Horse:", "'Speed':"
  28.     For i = 1 To 6
  29.         p = Rnd * pHorse(i) * 100
  30.         Print i, p
  31.         races(i) = races(i) + p
  32.     Next
  33.     _Delay 25 / nRaces
  34. Print "After"; nRaces; " races, these are the averages for horses"
  35. Print "Horse:", "'Speed':"
  36. For i = 1 To 6
  37.     Print i, races(i) / nRaces
  38. If nRaces < 10000 Then nRaces = nRaces * 10: Erase races: GoTo moreRaces
  39.  
  40.  

At any single day at the races you don't have a clue which is the best horse, nor really after 10. 100 and things start to fall in place but still surprises.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Bad random numbers, or TIMER limitation...?
« Reply #14 on: October 26, 2021, 02:11:45 pm »
Yeah dump the idea of Randomize with Timer, not needed except at start of program to get different results each time you start the app, Unless You Start at Exactly the Same Timer Each Day!!! (That might make a clever prank.)