0

I wrote C program that defined a 2D matrix with m rows and n columns with random numbers (Either 0 or 1). The code is as following:

int i,j;
    int original_matrix[m][n];
    for (i=0; i<=m-1; i++){
        for (j=0; j<=n-1; j++){
            original_matrix[i][j] = rand() % 2;
        }
    }

It worked. For the next step, I want to create the matrix with a probability. For example, 1 is written into a cell with probability p and 0 is written with probability 1-p. Could you please share any ideas on this if you have?

2 Answers2

3

Since rand() gives you a value between 0 and RAND_MAX, you can get a value at particular perentage simply by choosing an appropriate threshold. For example, if RAND_MAX was 999, 42% of all values would be expected to be less than 420.

So you can use code like in the following complete program, to set up an appropriate threshold and test the distribution of your values:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(int argc, char *argv[]) {
    // Get threshold (defaults to ~PI%), seed random numbers.

    double percent = (argc > 1) ? atof(argv[1]) : .0314159;
    int threshold = round(RAND_MAX * percent);
    srand(time(0));

    // Work out distribution (millions of samples).

    int below = 0, total = 0;
    for (int i = 0 ; i < 1000000; ++i) {
        ++total;
        if (rand() < threshold) ++below;
    }

    // Output stats.

    printf("Using probability of %f, below was %d / %d, %f%%\n",
        percent, below, total, below * 100.0 / total);
}

Some sample runs, with varying desired probabilities:

Using probability of 0.031416, below was 31276 / 1000000, 3.127600%
Using probability of 0.031416, below was 31521 / 1000000, 3.152100%

Using probability of 0.421230, below was 420936 / 1000000, 42.093600%
Using probability of 0.421230, below was 421634 / 1000000, 42.163400%

Using probability of 0.175550, below was 175441 / 1000000, 17.544100%
Using probability of 0.175550, below was 176031 / 1000000, 17.603100%

Using probability of 0.980000, below was 979851 / 1000000, 97.985100%
Using probability of 0.980000, below was 980032 / 1000000, 98.003200%

Using probability of 0.000000, below was 0 / 1000000, 0.000000%
Using probability of 1.000000, below was 1000000 / 1000000, 100.000000%

So, the bottom line is: to acheive your desire of one having a probabilty p (a double value) and zero having the probability 1 - p, you need the following:

srand(time(0));                               // done once, seed generator.
int threshold = round(RAND_MAX * p);          // done once.
int oneOrZero = (rand() < threshold) ? 1 : 0; // done for each cell.

Just keep in mind the limits of rand(), the difference between (for example) probabilities 0.0000000000 and 0.0000000001 will most likely be non-existent, unless RAND_MAX is large enough to make a difference. I doubt you'll be using probabilities that fine but I thought I'd better mention it just in case.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

rand() % 2 gives you a probability of 0.5.

p is a float, so you'll look at How to generate random float number in C to generate a random value in a real range. The top answer gives us: float x = (float)rand()/(float)(RAND_MAX/a);

We want a equal to 1 for probabilities. So, to get 0 with a probability of p, the formula is:

int zeroWithAProbabilityOfP = (float)rand()/(float)RAND_MAX <= p;

Which can be also be written:

int zeroWithAProbabilityOfP = rand() <= p * RAND_MAX;

ps: if available, for precision reasons, you should favor arc4random() or arc4random_buf() instead of rand():

  • rand() precision is 1 / 0x7FFFFFFF (on macOS)
  • arc4random() precision is 1 / 0xFFFFFFFF (so twice better)

In that case, formula would be:

int zeroWithAProbabilityOfP = arc4random() <= p * UINT32_MAX;
Cœur
  • 37,241
  • 25
  • 195
  • 267