Go Down

Topic: Spot the Bug?  Not so random numbers. (Read 654 times) previous topic - next topic

Kevin Gunn

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);
}

The Clever Monkey

#1
May 15, 2009, 04:53 pm Last Edit: May 15, 2009, 04:54 pm by clvrmnky Reason: 1
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.
I yield() for co-routines.

Kevin Gunn

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

Coding Badly

How are mode and oldMode declared?

- Brian

Kevin Gunn

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.

westfw

I ran your code for a couple thousand iterations and didn't see any repeats:
Code: [Select]
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?

Kevin Gunn

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

westfw

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

Kevin Gunn

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!

AWOL

"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.

Go Up