Pages: [1]   Go Down
Author Topic: Spot the Bug?  Not so random numbers.  (Read 579 times)
0 Members and 1 Guest are viewing this topic.
Carrboro, NC
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Life is short:  Void the warranty.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi folks --

I have a little piece of code that's driving me bats.  On each loop the current value of mode should change randomly to anything other than its current value.  However, I find this code only works most of the time and I do get duplicates.

I originally did not cast the mode/oldMode values to int, but added that since I thought the longs might be read as different by the chip when I saw them as not.

Does anyone see what I'm missing?


void diag() {
  oldMode = mode;
  do {
    mode=random(0,5);
  } while(int(oldMode)==int(mode));
  Serial.print("Mode: ");
  Serial.print(mode);
  Serial.print(" Old Mode: ");
  Serial.print(oldMode);
  delay(1000);
}
Logged

Canada
Offline Offline
Full Member
***
Karma: 0
Posts: 246
Code Monkey
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

There is random, and there is random.

Or, more correctly, there is more pseudo-random.

On most modern computers a series of random numbers is actually a long series of numbers that is different only for different seeds.  See the random() docs:

Quote
If it is important for a sequence of values generated by random() to differ, on subsequent executions of a sketch, use randomSeed() to initialize the random number generator with a fairly random input, such as analogRead() on an unconnected pin.

Conversely, it can occasionally be useful to use pseudo-random sequences that repeat exactly. This can be accomplished by calling randomSeed() with a fixed number, before starting the random sequence.

There is a whole science of increasing the apparent randomness for pseudo-random numbers generating by computers.  For cryptography it can be very important to generate strong random sequences.

In the code you show here all we see is the call to random().  This implies that the same series of numbers could be fetched over and over again.
« Last Edit: May 15, 2009, 09:54:11 am by clvrmnky » Logged

I yield() for co-routines.

Carrboro, NC
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Life is short:  Void the warranty.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

True -- I'm very familiar with the pseudo-random nature of the numbers, but that is not the problem.  The problem is not that the numbers are not random enough, but that the code exits the do-while loop SOMETIMES when both the current and previous values of the numbers are the same.

What should happen is that as long as my new value and old value are the same the code should generate another random number.  Only when the values differ from one another should the loop exit.

Here's the plain english version of the code:

1) Set "old value" to equal the current value.
2) Generate a random number and store it as the current value.
3) If the current value is the same as the old value try again (i.e.: go back to step #2).  Otherwise, the new value is acceptable.

Most of the time it does exactly what I expect.  Periodically, though, it fails.  I can't figure out why...
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 207
Posts: 12904
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

How are mode and oldMode declared?

- Brian
Logged

Carrboro, NC
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Life is short:  Void the warranty.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Both are declared as long since that's what random returns.

I've tried a variety of casts to int before testing, but no joy there either.

I think I'm going to try declaring them as integers and then set mode using

mode = int(random(0,5));

I've still been wondering if somewhere what I see and what the chip sees aren't a little different -- which could definitely cause the comparison to pass when it shouldn't.
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 133
Posts: 6749
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I ran your code for a couple thousand iterations and didn't see any repeats:
Code:
long oldMode, mode;

void setup()                    // run once, when the sketch starts
{
  Serial.begin(19200);
  for (int i=0; i < 1000; i++) {
    oldMode = mode;
    do {
      mode=random(0,5);
    }
    while(int(oldMode)==int(mode));
    Serial.print("Mode: ");
    Serial.print(mode);
    Serial.print(" Old Mode: ");
    Serial.print(oldMode);
    if (mode == oldMode) {
      Serial.println(" ******");
    }
    else {
      Serial.println(" ");
    }
    delay(30);
  }
You do have oldMode declared in the global context, right?
Logged

Carrboro, NC
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Life is short:  Void the warranty.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks!  Yes, the variables are declared globally.  This is getting more mysterious to me.

I'll try running your copy of the code via copy/paste.  If I still see duplicates I suspect I could be looking at strange hardware behavior.  Although the board resets whenever I reload code, it hasn't been power-cycled in weeks... hmm...
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 133
Posts: 6749
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Add code in setup that shows "for sure" when the Arduino reloads?
Logged

Carrboro, NC
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Life is short:  Void the warranty.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

THANKS EVERYONE!

What a great community this is...

I haven't found the error, but I've found the "why".  The problem lies elsewhere in the program -- turns out my main loop() is going places other than just the one function I expected.  Variables get changed then sent back to the correct function.  Time for a little Friday night debugging!
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26281
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you don't want repeats, use XOR.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Pages: [1]   Go Up
Jump to: