Random Numbers

From Nutwiki
Jump to: navigation, search

Test Environments

Hardware Comments Nut/OS
4.8.7
Ethernut 1.3 H OK
Binaries
Compiler: AVR-GCC 4.3.2
Ethernut 2.1 B OK
Binaries
Compiler: AVR-GCC 4.3.2
Ethernut 3.0 E OK
Binaries
Compiler: ARM-GCC 4.3.3

Overview

This example demonstrates how to set up and use pseudo-random numbers with your Nut/OS application.

Source Code

<source lang="c">

  1. include <dev/board.h>
  2. include <stdio.h>
  3. include <io.h>
  4. include <time.h>
  5. include <sys/timer.h>

int main(void) {

   unsigned long baud = 115200;
   NutRegisterDevice(&DEV_DEBUG, 0, 0);
   freopen(DEV_DEBUG_NAME, "w", stdout);
   _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
   puts("\nNut/OS Random Numbers Demo");
   /* initialize the random seed */
   srand(time(NULL));
   puts("We will now be generating a pseudo-random number each second...");
   /* calculate "random" numbers */
   for (;;) {
       printf("%d... ", rand());
       NutSleep(1000);
   }
   return 0;

} </source>

Details

<source lang="c"> unsigned long baud = 115200;

NutRegisterDevice(&DEV_DEBUG, 0, 0); freopen(DEV_DEBUG_NAME, "w", stdout); _ioctl(_fileno(stdout), UART_SETSPEED, &baud);

puts("\nNut/OS Random Numbers Demo");

</source>

In order to get started we initialize the debug device and tell the user the application name.

<source lang="c"> /* initialize the random seed */ srand(time(NULL)); </source>

Although this part is incredibly short, it requires some explanation. First of all: The rand() function does not return random numbers. What it does return is a pseudo-random number that is generated by a convoluted algorithm. Now the problem with any deterministic algorithm is that given the same input values it will always output the same output values. This is valid for the numbers that are generated by rand() as well.

Since that is obviously not very useful and nobody needs random numbers that aren't, you know, random, there is the idea of a "random seed". This number decides which sequences of numbers rand() will output.

In order to make the random numbers as "random-y" as possible, we set the random seed to a value that is likely to be different every time our program runs: The current time.

So in short: srand(time(NULL)); -> We set the random seed to our current time.

<source lang="c"> /* calculate "random" numbers */ for (;;) {

   printf("%d... ", rand());
   NutSleep(1000);

} </source>

With the random seed set, obtaining a random number is as simple as calling rand(). This is exactly what we do here: Output a random number, then wait a second. That's all there is to random numbers.

One thing to note: Nut/OS doesn't have its own rand() and srand(), it reuses the ones from the runtime libs (avr-libc on AVR/newlib on ARM and AVR32 respectively) so there may be slight differences with the numbers a given random seed outputs.

And one final hint: If you want to limit the maximum value of the random number you get, simply do something like

<source lang="c"> myvar = rand() % MAXIMUM_VALUE; </source>

where MAXIMUM_VALUE can be a number, numeric variable or define. Note that the resulting number will always be below the maximum value.

Security note

Please note, that the pseudo-random numbers produced by rand() are not cryptographically secure. If you need random numbers for security appliances avoid the rand() function and use a dedicated cryptographically secure pseudo random number generator and use a better seed than the current time.

Output

<source lang="text"> Nut/OS Random Numbers Demo We will now be generating a pseudo-random number each second... 20034... 24315... 12703... 22240... 10073... 18561... 20058... 5761... 8550... 1 2705... 17166... 2396... 12622... </source>

See also