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?
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.
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;
I know you can use rand() % 2 to get a random choice of 0 and 1 in C, but is there something more efficient?
My question is not so much about C specifically but about how random number generators work. If I understand correctly, they do some complicated math on the seed to get an even distribution between 0 and RAND_MAX, but is there a way to do less math if you just need a binary choice?
Thanks
is there a way to do less math if you just need a binary choice?
Yes, but it depends on how "good" a random distribution and sequence (or apparent lack) is required. C does not specify the quality of rand(). With quality of randomness specified, alternative solutions exist. How fast? - it depends on many things not supplied by OP. If code is to use rand(), the below will modestly improve performance over a simple rand() % 2u
Call rand() once in a while to extract n random bits and use 1 of those bits per call.
This function uses RAND_MAX to rate the number of bits n received per rand() call. A value of RAND_MAX == 32767 or 0x7FFF would imply 15 random bits.
int rand01(void) {
// Insure RAND_MAX is a power-of-2 - 1
assert(((RAND_MAX + 1u) & RAND_MAX) == 0);
static unsigned rmax = 0;
static int rbits;
if (rmax == 0) {
rmax = RAND_MAX;
rbits = rand();
}
rmax /= 2u;
int r = rbits%2u;
rbits /= 2u;
return r;
}
Note that this approach does not reset the random state completely with srand() . A srand() call is not aware of this function's state.
maybe you can try using my method:
int i;
i = time(NULL) % 2;
this only works if you don't do more than one random per second but you can also do:
struct timeval tv;
gettimeofday(&tv,NULL);
unsigned long random_number = (1000000 * tv.tv_sec + tv.tv_usec) % 2;
this will update your random number at a microsec rate.
How can i generate float random values in C? (also negative)
In general to generate random numbers from an arbitrary distribution you'd first generate uniform random numbers and then pass them to the inverse of the cumulative distribution function.
Assume for example that you want random numbers with uniform distribution on the interval [-10.0, 10.0] and all you've got is random numbers from [0.0, 1.0]. Cumulative distribution function of the uniform distribution on [-10.0, 10.0] is:
cdf(x) = 0.05 * x + 0.5 for x in [-10.0, 10.0]
This expresses the probability that a random number generated is smaller than x. The inverse is
icdf(y) = 20.0 * y - 10.0 for y in [0.0, 1.0]
(You can obtain this easily on paper by switching the x and y axis).
Hence to obtain random numbers uniformly distributed on [-10.0, 10.0] you can use the following code:
#include <stdlib.h>
// Returns uniformly distributed random numbers from [0.0, 1.0].
double uniform0to1Random() {
double r = random();
return r / ((double)RAND_MAX + 1);
}
// Returns uniformly distributed random numbers from [-10.0, 10.0].
double myRandom() {
return 20.0 * uniform0to1Random() - 10.0;
}
In fact, you don't need uniform0to1Random() since there are already a lot of good uniform random numbers generators from [0.0, 1.0] (e.g. in the boost library).
You can use the method to generate random numbers with nearly any probability distribution you want by sampling the inverse cumulative distribution as shown above.
See http://en.wikipedia.org/wiki/Inverse_transform_sampling for more details.
Following will give you a float in range between -max/2 up to +max/2:
float max = 5000;
float r = max * ((float)rand()/(float)RAND_MAX - 0.5);
Edit Since the question was edited for C only:
This page is pretty helpful: http://www.geekpedia.com/tutorial39_Random-Number-Generation.html
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
//use this first function to seed the random number generator,
//call this before any of the other functions
void initrand()
{
srand((unsigned)(time(0)));
}
//generates a psuedo-random float between 0.0 and 0.999...
float randfloat()
{
return rand()/(float(RAND_MAX)+1);
}
//generates a psuedo-random float between 0.0 and max
float randfloat(float max)
{
return randfloat()*max;
}
//generates a psuedo-random float between min and max
float randfloat(float min, float max)
{
if (min>max)
return randfloat()*(min-max)+max;
else
return randfloat()*(max-min)+min;
}
//generates a psuedo-random double between 0.0 and 0.999...
double randdouble()
{
return rand()/(double(RAND_MAX)+1);
}
//generates a psuedo-random double between 0.0 and max
double randdouble(double max)
{
return randdouble()*max;
}
//generates a psuedo-random double between min and max
double randdouble(double min, double max)
{
if (min>max)
return randdouble()*(min-max)+max;
else
return randdouble()*(max-min)+min;
}
int main()
{
for (int i=0; i<10; i++)
printf("%f\n", randdouble(-1,3));
}
Output sample:
2.360751
0.577532
2.132397
2.193760
2.646589
-0.209795
0.340891
2.072918
0.111099
1.215880
(note the range: -1..3)
The GNU scientific library has a few methods.
http://www.gnu.org/s/gsl/manual/html_node/Random-number-generator-algorithms.html
Even if you can't use it due to licensing it should give you the names of a few too google for.
The boost random library (C++) uses lagged fibonacci and ranlux algorithms for doubles and floats, so they may be another option for you. (The methods not the boost library as it is C++ )
These techniques usually give you results in the range 0 -- 1. By using R = rmin + v* (rmax-rmin) where v is in 0 -- 1 you will get R in rmin -- rmax
Take a look at Boost.Random:
http://www.boost.org/doc/libs/1_47_0/doc/html/boost_random.html
You can get float random values doing this way:
boost::mt19937 base_rng;
boost::uniform_01<> u01;
boost::variate_generator<boost::mt19937&, boost::uniform_01<> > rng(base_rng, u01);
rng(); // draws a random number
Please note that random number generation facilities are now available in the new C++ standard:
http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01617.html
You can use
rand() / (double)RAND_MAX /* 0 <= random number <= 1 */
rand() / (RAND_MAX + 1.0) /* 0 <= random number < 1 */
for a random number between 0 and 1.
Then multiply by your desired range and add for the initial value.
For instance, to get random numbers 0 <= X < 4.2
double tmp = rand() / (RAND_MAX + 1.0)
X = tmp * 4.2;
to get random numbers -21.1 <= X <= 37.5
double tmp = rand() / (double)RAND_MAX
X = tmp * (37.5 + 21.1);
X = X - 21.1;
The simplest method I know:
int randNum = rand();
float floatRand = randNum/RAND_MAX;
floatRand is a random float in [0,1]. However, the resolution of this method is limited by RAND_MAX..
[EDIT]:
to get negative values, generate another random number and if its greater than RAND_MAX/2, multiply the former by (-1).
This will generate random [any representable float]:
#include <stdio.h>
float randfdev(void)
{
float tmp;
int fd = open("/dev/urandom",O_RDONLY);
read(fd,&tmp,sizeof tmp);
return tmp;
}
Note:
no error checking
assumes IEEE floating point, although other formats should work
will produce NaNs, subnormals, infinitys, etc
srand(time(null));
printf("%d", rand());
Gives a high-range random number (0-32000ish), but I only need about 0-63 or 0-127, though I'm not sure how to go about it. Any help?
rand() % (max_number + 1 - minimum_number) + minimum_number
So, for 0-65:
rand() % (65 + 1 - 0) + 0
(obviously you can leave the 0 off, but it's there for completeness).
Note that this will bias the randomness slightly, but probably not anything to be concerned about if you're not doing something particularly sensitive.
You can use this:
int random(int min, int max){
return min + rand() / (RAND_MAX / (max - min + 1) + 1);
}
From the:
comp.lang.c FAQ list · Question 13.16
Q: How can I get random integers in a certain range?
A: The obvious way,
rand() % N /* POOR */
(which tries to return numbers from 0 to N-1) is poor, because the
low-order bits of many random number generators are distressingly
non-random. (See question 13.18.) A better method is something like
(int)((double)rand() / ((double)RAND_MAX + 1) * N)
If you'd rather not use floating point, another method is
rand() / (RAND_MAX / N + 1)
If you just need to do something with probability 1/N, you could use
if(rand() < (RAND_MAX+1u) / N)
All these methods obviously require knowing RAND_MAX (which ANSI #defines in <stdlib.h>), and assume that N is much less than RAND_MAX. When N is close to RAND_MAX, and if the range of the random number
generator is not a multiple of N (i.e. if (RAND_MAX+1) % N != 0), all
of these methods break down: some outputs occur more often than
others. (Using floating point does not help; the problem is that rand
returns RAND_MAX+1 distinct values, which cannot always be evenly
divvied up into N buckets.) If this is a problem, about the only thing
you can do is to call rand multiple times, discarding certain values:
unsigned int x = (RAND_MAX + 1u) / N;
unsigned int y = x * N;
unsigned int r;
do {
r = rand();
} while(r >= y);
return r / x;
For any of these techniques, it's straightforward to shift the range,
if necessary; numbers in the range [M, N] could be generated with
something like
M + rand() / (RAND_MAX / (N - M + 1) + 1)
(Note, by the way, that RAND_MAX is a constant telling you what the
fixed range of the C library rand function is. You cannot set RAND_MAX
to some other value, and there is no way of requesting that rand
return numbers in some other range.)
If you're starting with a random number generator which returns
floating-point values between 0 and 1 (such as the last version of
PMrand alluded to in question 13.15, or drand48 in question
13.21), all you have to do to get integers from 0 to N-1 is
multiply the output of that generator by N:
(int)(drand48() * N)
Additional links
References: K&R2 Sec. 7.8.7 p. 168
PCS Sec. 11 p. 172
Quote from: http://c-faq.com/lib/randrange.html
check here
http://c-faq.com/lib/randrange.html
For any of these techniques, it's straightforward to shift the range, if necessary; numbers in the range [M, N] could be generated with something like
M + rand() / (RAND_MAX / (N - M + 1) + 1)
Taking the modulo of the result, as the other posters have asserted will give you something that's nearly random, but not perfectly so.
Consider this extreme example, suppose you wanted to simulate a coin toss, returning either 0 or 1. You might do this:
isHeads = ( rand() % 2 ) == 1;
Looks harmless enough, right? Suppose that RAND_MAX is only 3. It's much higher of course, but the point here is that there's a bias when you use a modulus that doesn't evenly divide RAND_MAX. If you want high quality random numbers, you're going to have a problem.
Consider my example. The possible outcomes are:
rand()
freq.
rand() % 2
0
1/3
0
1
1/3
1
2
1/3
0
Hence, "tails" will happen twice as often as "heads"!
Mr. Atwood discusses this matter in this Coding Horror Article
The naive way to do it is:
int myRand = rand() % 66; // for 0-65
This will likely be a very slightly non-uniform distribution (depending on your maximum value), but it's pretty close.
To explain why it's not quite uniform, consider this very simplified example:
Suppose RAND_MAX is 4 and you want a number from 0-2. The possible values you can get are shown in this table:
rand() | rand() % 3
---------+------------
0 | 0
1 | 1
2 | 2
3 | 0
See the problem? If your maximum value is not an even divisor of RAND_MAX, you'll be more likely to choose small values. However, since RAND_MAX is generally 32767, the bias is likely to be small enough to get away with for most purposes.
There are various ways to get around this problem; see here for an explanation of how Java's Random handles it.
rand() will return numbers between 0 and RAND_MAX, which is at least 32767.
If you want to get a number within a range, you can just use modulo.
int value = rand() % 66; // 0-65
For more accuracy, check out this article. It discusses why modulo is not necessarily good (bad distributions, particularly on the high end), and provides various options.
As others have noted, simply using a modulus will skew the probabilities for individual numbers so that smaller numbers are preferred.
A very ingenious and good solution to that problem is used in Java's java.util.Random class:
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}
It took me a while to understand why it works and I leave that as an exercise for the reader but it's a pretty concise solution which will ensure that numbers have equal probabilities.
The important part in that piece of code is the condition for the while loop, which rejects numbers that fall in the range of numbers which otherwise would result in an uneven distribution.
double scale = 1.0 / ((double) RAND_MAX + 1.0);
int min, max;
...
rval = (int)(rand() * scale * (max - min + 1) + min);
Updated to not use a #define
double RAND(double min, double max)
{
return (double)rand()/(double)RAND_MAX * (max - min) + min;
}
If you don't overly care about the 'randomness' of the low-order bits, just rand() % HI_VAL.
Also:
(double)rand() / (double)RAND_MAX; // lazy way to get [0.0, 1.0)
This answer does not focus on the randomness but on the arithmetic order.
To get a number within a range, usually we can do it like this:
// the range is between [aMin, aMax]
double f = (double)rand() / RAND_MAX;
double result = aMin + f * (aMax - aMin);
However, there is a possibility that (aMax - aMin) overflows. E.g. aMax = 1, aMin = -DBL_MAX. A safer way is to write like this:
// the range is between [aMin, aMax]
double f = (double)rand() / RAND_MAX;
double result = aMin - f * aMin + f * aMax;
Based on this concept, something like this may cause a problem.
rand() % (max_number + 1 - minimum_number) + minimum_number
// 1. max_number + 1 might overflow
// 2. max_number + 1 - min_number might overflow
if you care about the quality of your random numbers don't use rand()
use some other prng like http://en.wikipedia.org/wiki/Mersenne_twister or one of the other high quality prng's out there
then just go with the modulus.
Just to add some extra detail to the existing answers.
The mod % operation will always perform a complete division and therefore yield a remainder less than the divisor.
x % y = x - (y * floor((x/y)))
An example of a random range finding function with comments:
uint32_t rand_range(uint32_t n, uint32_t m) {
// size of range, inclusive
const uint32_t length_of_range = m - n + 1;
// add n so that we don't return a number below our range
return (uint32_t)(rand() % length_of_range + n);
}
Another interesting property as per the above:
x % y = x, if x < y
const uint32_t value = rand_range(1, RAND_MAX); // results in rand() % RAND_MAX + 1
// TRUE for all x = RAND_MAX, where x is the result of rand()
assert(value == RAND_MAX);
result of rand()
2 cents (ok 4 cents):
n = rand()
x = result
l = limit
n/RAND_MAX = x/l
Refactor:
(l/1)*(n/RAND_MAX) = (x/l)*(l/1)
Gives:
x = l*n/RAND_MAX
int randn(int limit)
{
return limit*rand()/RAND_MAX;
}
int i;
for (i = 0; i < 100; i++) {
printf("%d ", randn(10));
if (!(i % 16)) printf("\n");
}
> test
0
5 1 8 5 4 3 8 8 7 1 8 7 5 3 0 0
3 1 1 9 4 1 0 0 3 5 5 6 6 1 6 4
3 0 6 7 8 5 3 8 7 9 9 5 1 4 2 8
2 7 8 9 9 6 3 2 2 8 0 3 0 6 0 0
9 2 2 5 6 8 7 4 2 7 4 4 9 7 1 5
3 7 6 5 3 1 2 4 8 5 9 7 3 1 6 4
0 6 5
Just using rand() will give you same random numbers when running program multiple times. i.e. when you run your program first time it would produce random number x,y and z. If you run the program again then it will produce same x,y and z numbers as observed by me.
The solution I found to keep it unique every time is using srand()
Here is the additional code,
#include<stdlib.h>
#include<time.h>
time_t t;
srand((unsigned) time(&t));
int rand_number = rand() % (65 + 1 - 0) + 0 //i.e Random numbers in range 0-65.
To set range you can use formula : rand() % (max_number + 1 - minimum_number) + minimum_number
Hope it helps!
You can change it by adding a % in front of the rand function in order to change to code
For example:
rand() % 50
will give you a random number in a range of 50. For you, replace 50 with 63 or 127
I think the following does it semi right. It's been awhile since I've touched C. The idea is to use division since modulus doesn't always give random results. I added 1 to RAND_MAX since there are that many possible values coming from rand including 0. And since the range is also 0 inclusive, I added 1 there too. I think the math is arranged correctly avoid integer math problems.
#define MK_DIVISOR(max) ((int)((unsigned int)RAND_MAX+1/(max+1)))
num = rand()/MK_DIVISOR(65);
Simpler alternative to #Joey's answer. If you decide to go with the % method, you need to do a reroll to get the correct distribution. However, you can skip rerolls most of the time because you only need to avoid numbers that fall in the last bucket:
int rand_less_than(int max) {
int last_bucket_min = RAND_MAX - RAND_MAX % max;
int value;
do {
value = rand();
} while (last_bucket_min <= value);
return value % max;
}
See #JarosrawPawlak's article for explanation with diagrams: Random number generator using modulo
In case of RAND_MAX < max, you need to expand the generator: Expand a random range from 1–5 to 1–7
#include <stdio.h>
#include <stdlib.h>
#include <time.h> // this line is necessary
int main() {
srand(time(NULL)); // this line is necessary
int random_number = rand() % 65; // [0-64]
return 0;
}
Foy any range between min_num and max_num:
int random_number = rand() % (max_num + 1 - min_num) + min_num;