10 years, 1 month ago.

Why is the rand() function not the least bit random in the LPC11u24 MBED ?

I have a simple little LED array blinker program, I'm trying to blink random LED's, but the rand() function is returning a semi-random but very consistent sequence of numbers... not random at all..

I've tried seeding it with a number read from the analogue inputs for some randomness, but that doesn;t seem to help at all, the number sequence I get back from rand() is always the same...

A simple loop demonstrates this...

#include "mbed.h"
int main() {
  while (1) {
    printf("%i ",rand()%16);
  }
}

returns the following series of numbers endlessly...

start sequence -> 1 0 12 15 15 6 10 5 13 12 8 11 11 2 6 1 9 8 4 7 7 14 2 13 5 4 0 3 3 10 14 9 1 <- repeat sequence again... 0 12 15 15

4 Answers

9 years, 8 months ago.

Most run-time library pseudo-random number generators are exceptionally weak and show exactly the problems you've highlighted. I'd put money on them using a Linear Congruential Generator - see http://en.wikipedia.org/wiki/Linear_congruential_generator#Advantages_and_disadvantages_of_LCGs for an overview on it. If you want true pseudo-random numbers then you'd have to implement something in hardware (some chips have true hardware random number generators built in).

10 years, 1 month ago.

Maybe you need to call srand(time(NULL)):

http://www.cplusplus.com/reference/cstdlib/rand/

10 years, 1 month ago.

I tried that but it did not have any effect on the lack of randomness, in the end I've resorted to implementing my own simple but effective random number generator and for this application it works fine...

Would you mind sharing what you came up with? I also noticed the "not very random" randomness in an app I wrote, but it wasn't worth the hassle of fixing it.

posted by Aaron Minner 16 Mar 2014

Sure, no problem, I just googled simple psuedo random number generators and went for the simplest one I could find, it is probably a very often used algorithm (I seem to remember the ancient Sinclair ZX Spectrum using something very similar when I was young and keen enough to study the Spectrum ROM Diassembly book in great detail).

I added two unsigned integer variables to the scope of the program, m_z and m_w, that are effectively the seeds to the RNG, just ensure that they don't both start at 0, I chose two numbers at random but you could create an srnd() function to do this too.

unsigned int m_z=12434,m_w=33254;

unsigned int rnd() {
    m_z = 36969 * (m_z & 65535) + (m_z >>16);
    m_w = 18000 * (m_w & 65535) + (m_w >>16);
    return ((m_z <<16) + m_w);
}

The function returns a very reasonable approximation of a random number between 0 and sizeof(int), I use things like rnd()%15 to obtain numbers between 0 and 14 for example.

PS. I have no idea why this very simple function produces a random looking stream of numbers but its good enough for my simple use, the google references have much more info on this.

Peter

posted by Peter Wilson 16 Mar 2014
10 years, 1 month ago.

The random number generator needs a seed to work correctly. srand(time(NULL)) normally does this fine since it gives a different seed every time if your system has a clock that is correct. Unfortunately in this case about the only sense of time you have is time since the power on reset finished which is going to be the same every time.

One way to generate a random number would be to connect one of the ADC inputs so that it's floating in the middle of the range (say 100k to ground and 100k to 3.3v) and then read the ACD value. You then only look at the least significant bit of the value, that should normally be fairly random. Repeat 31 more times so that you have 32 random bits and use that value to seed the random number generator.