A Nifty Random Number Trick

I don’t believe I’ll ever absorb all the wondrous potential of Linux/Unix. Case in point is the /dev/random file. It’s exactly what the name implies: random stuff. And you can use this nifty file in your C programs to generate random values.

Available in Linux, Unix, and macOS (sorry, Windows), the /dev/random file is classified as a special character file type. Its purpose is to generate random values. If you use the cat command to “view” it, you see garbage puke all over the terminal window; press Ctrl+C to halt the spew. (The random output can inadvertently mess with some terminal settings, so be careful.)

According to the all-knowing Wikipedia, the file uses “noise” from various device drivers to generate its random values. That’s good enough for me, and a reliable way on a *NIX box to obtain a random value, as shown in this code:

2022_10_22-Lesson-a.c

#include <stdio.h>

int main()
{
    const char filename[] = "/dev/random";
    FILE *dr;
    int c;

    dr = fopen(filename,"r");
    if( dr )
    {
        c = fgetc(dr);
        printf("Random value: %d\n",c);
        fclose(dr);
    }
    return(0);
}

The /dev/random file is declared as a string constant at Line 5. It’s a character file, so I use the stream oriented fopen() function at Line 9 to open it for reading. Upon success, the if statements execute, fetching a single character (int variable c) from the file and outputting it at Line 13. The file is closed at Line 14. Note that you don’t need to seed a randomizer to employ this technique.

Here is the output:

Random value: 169

This update to the code reads ten values from the file:

2022_10_22-Lesson-b.c

#include <stdio.h>

int main()
{
    const char filename[] = "/dev/random";
    const int size = 10;
    FILE *dr;
    int c,x;

    dr = fopen(filename,"r");
    if( dr )
    {
        for( x=0; x<size; x++ )
        {
            c = fgetc(dr);
            printf("Random value: %d\n",c);
        }
        fclose(dr);
    }
    return(0);
}

Constant int value size sets the number of integers to output. A for loop is added to fetch and output the ten values:

Random value: 131
Random value: 105
Random value: 172
Random value: 54
Random value: 158
Random value: 185
Random value: 201
Random value: 110
Random value: 73
Random value: 67

To gobble all ten values into an array, I updated the code to use the fread() function to consume the array in a single gulp:

2022_10_22-Lesson-c.c

#include <stdio.h>

int main()
{
    const char filename[] = "/dev/random";
    const int size = 10;
    FILE *dr;
    int r[size];
    int x;

    dr = fopen(filename,"r");
    if( dr )
    {
        fread(&r,sizeof(int),size,dr);
        for( x=0; x<size; x++ )
        {
            printf("Random value: %d\n",r[x]);
        }
        fclose(dr);
    }
    return(0);
}

Array r[] is declared at Line 8. The fread() function at Line 14 grabs the ten integers at once, setting them into the array. A for loop outputs the values; the output is similar to the preceding example.

To read larger values, again I use the fread() function to procure an unsigned long integer value from the /dev/random file:

2022_10_22-Lesson-d.c

#include <stdio.h>

int main()
{
    const char filename[] = "/dev/random";
    FILE *dr;
    unsigned long r;

    dr = fopen(filename,"r");
    if( dr )
    {
        fread(&r,sizeof(unsigned long),1,dr);
        printf("Random value: %lu\n",r);
        fclose(dr);
    }
    return(0);
}

The fread() function at Line 12 specifies the size of an unsigned long value, reading the value from open file dr and setting into variable r. Here is sample output:

Random value: 15304796159533619025

You can read real numbers as well. This code update consumes a double value from the /dev/random file:

2022_10_22-Lesson-e.c

#include <stdio.h>

int main()
{
    const char filename[] = "/dev/random";
    FILE *dr;
    double r;

    dr = fopen(filename,"r");
    if( dr )
    {
        fread(&r,sizeof(double),1,dr);
        printf("Random value: %f\n",r);
        fclose(dr);
    }
    return(0);
}

The output here is interestingly whacky:

Random value: -3581507666920258283702881838842193028636242448207
7114148082694520146327147739765556024935895227752040177045026700
73182756975969049482863570233961353096133083136.000000

Do consider using this approach when your code needs a quick-and-dirty yet random value. This trick is yet another nifty thing about Linux and similar operating systems.

Leave a Reply