I'm trying to generate a simple random number in C with the raspberry pi. The code compiles fine but when running it the number is not random, its 384 each time.
Where am I going wrong?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf ("Random number generator\n") ;
int x = (rand() % 1000) + 1;
printf("%d\n", x);
return 0 ;
}
You need to seed the random number generator with some naturally random value like the current time. Something like:
srand (time(NULL));
Update: note that you will need to add an include for the time library if you use the example above:
include <time.h>
Use this function to generate random value. also make sure to add the library include <time.h>.
// Random value will be from 0 to #
int GenerateRandomInt (int MaxValue)
{
unsigned int iseed = (unsigned int)time(NULL); //Seed srand() using time() otherwise it will start from a default value of 1
srand (iseed);
int random_value = (int)((1.0 + MaxValue) * rand() / ( RAND_MAX + 1.0 ) ); //Scale rand()'s return value against RAND_MAX using doubles instead of a pure modulus to have a more distributed result.
return(random_value);
}
Related
I'm trying to generate a random-number sequence with rand().
I have something like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int Random(int min, int max)
{
/* returns a random integer in [min, max] */
double uniform; // random variable from uniform distribution of [0, 1]
int ret; // return value
srand((unsigned int)clock());
uniform = rand() / (double)RAND_MAX;
ret = (int)(uniform * (double)(max - min)) + min;
return ret;
}
int main(void)
{
for(int i=0; i<10; i++)
printf("%d ", Random(0, 100));
printf("\n");
return 0;
}
It made different results when executed on macOS v10.14 (Mojave) and UbuntuĀ 18.04 (Bionic Beaver).
It works on Ubuntu:
76 42 13 49 85 7 43 28 15 1
But not on macOS:
1 1 1 1 1 1 1 1 1 1
Why doesn't it work well on macOS? Is there something different in random number generators?
I'm a Mac user. To generate random numbers I initialise the seed like this:
srand(time(NULL));
Plus, try initialising it in your main.
If reproducible "random" numbers are something you care about, you should avoid the rand function. The C standard doesn't specify exactly what the sequence produced by rand is, even if the seed is given via srand. Notably:
rand uses an unspecified random number algorithm, and that algorithm can differ between C implementations, including versions of the same standard library.
rand returns values no greater than RAND_MAX, and RAND_MAX can differ between C implementations.
Instead, you should use an implementation of a pseudorandom number generator with a known algorithm, and you should also rely on your own way to transform pseudorandom numbers from that algorithm into the numbers you desire. (For many ways to do so, see my page on sampling algorithms. Note that there are other things to consider when reproducibility is important.)
See also the following:
Does Python have a function to mimic the sequence of C's rand()?
Why is the use of rand() considered bad?
How predictable is the result of rand() between individual systems?
rand is obsolete in Mac. Use random() instead.
toZero = rand() % N;
This line of code is giving me Clang-Tidy: rand() has limited randomness. Why is this warning coming up? How can I fix it?
Despite rand() being adequate for very many applications (particularly with extensions like Park-Miller and Bays-Durham shuffling), some code checking tools equate it with a scaled down version of the devil.
Clang-Tidy is warning you that it might not have sufficient properties of randomness for your needs.
Would it be possible to send me a code snippet where Clang-Tidy doesn't warn me while using rand()?
If you are sticking with rand(), you must disable the warning:
toZero = rand() % N; // NOLINT(cert-msc30-c, cert-msc50-cpp)
A better option would be to use the <random> library and functions instead.
One example:
#include <iostream>
#include <random>
#include <type_traits>
// A function to return a seeded random number generator.
inline std::mt19937& generator() {
// the generator will only be seeded once (per thread) since it's static
static thread_local std::mt19937 gen(std::random_device{}());
return gen;
}
// A function to generate integers in the range [min, max]
template<typename T, std::enable_if_t<std::is_integral_v<T>>* = nullptr>
T my_rand(T min, T max) {
std::uniform_int_distribution<T> dist(min, max);
return dist(generator());
}
// A function to generate floats in the range [min, max)
template<typename T, std::enable_if_t<std::is_floating_point_v<T>>* = nullptr>
T my_rand(T min, T max) {
std::uniform_real_distribution<T> dist(min, max);
return dist(generator());
}
int main() {
unsigned N = 100;
std::cout << my_rand(0U, N - 1) << '\n'; // unsigned int:s instead of rand() % N
std::cout << my_rand(-5., 5.) << '\n'; // double's
}
The function rand() is not a C++ function but a C function. It is from stdlib.h, and defined in ISO/IEC 9899 (The C Programming Language).
It does not guarantee a portable level of high randomness.
There are many different implementations possible and no proper quality control in the standard.
A typical implementation of rand() is:
static int next = (int) time();
int rand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
That is, most of the times, rand() is a PRNG and does not use any entropy at all, except maybe for the initial value of next.
So what you should use is the C++11 random library. Here's how it works:
#include <random>
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(1, 6);
auto dice = std::bind(distribution, generator);
int roll = dice();
DEMO : https://pastebin.run/pzhw6s36g9mf
Notes:
The uniform_int_distribution<int> generates a distribution function that will retrieve numbers from the underlying generator that are evenly distributed between the given range. This is important: Modulo is not an even distribution function. Just doing something like int roll = 1 + nextInt() % 6 is not evenly distributed. (Thanks to Christian Hujer)
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;
For example, we can use internal rand(), but it is the worst choice:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
float randoms(float min, float max)
{
return (float)(rand())/RAND_MAX*(max - min) + min;
}
int main()
{
srand((unsigned int)time(0));
printf("%f\n",randoms(-100.001, 100.001));
return 0;
}
I've searched, but not found any working example of PCG library for float numbers.
In the answer I would like to share my own experience of using PCG random library to generate float numbers within a fixed range. Previously I've used arc4random library for this goal, but PCG is simpler and has no complicated dependencies.
How to generate float numbers set within a range(?)
Using various random functions can improve the random properties of integers generated. The application of those integers to make a float has other pitfalls not address by OP regardless of the random function. Also see #Serge Ballesta.
The simplistic use of the following risks generating a value outside the range [min...max]
float retval = (float)some_rand()/SOME_RAND_MAX*(max - min) + min;
The 2 conversion of the 2 integers to float incur rounding. float /,*,-,* each can contribute 4 more roundings. Given that min/max may come in many valid combinations, it is prudent to guard against an out-of-range retval
float retval;
assert(min < max); // may want to assert min/max are finite too
do {
retval = 1.0f*some_rand()/SOME_RAND_MAX*(max - min) + min;
} while (!(retval >= min && retval <= max));
return retval;
Note that the setting of FLT_EVAL_METHOD complicates any assessment as some calculations may be conducted as double/long double.
Potential losses of desired random properties:
The use of pcg32_random_r() versus rand() does provide numbers with more attractive integer random properties, yet those improved attributes are reduced with casual floating-point code.
(Assume binary32 for float)
Consider how the following can uniformly generate values in the range [0...224] yet values larger than that, it will be only even numbers. It becomes spottier with larger numbers up to (float)UINT32_MAX. This would be acceptable for another function that was now to return that value, but the scaling of *(max - min) + min redistributes those values in a way that can become very non-uniform.
(float)pcg32_random_r(...);
A simple way to address some of these short comings is to use higher precision like double math within float randoms(float min, float max), yet that approach does not help with long double randomsL(long double min, long double max)
You PCG will generate some number of random bits. Let's say that's 32. A double precision float has 53 bits of significand, so you'll need more than one call. So, call the function twice, and pack the two calls into a 64-bit integer:
int64_t x = (pcg32() << 32) | pcg32();
Then divide that integer down to the desired range (this is the signed -100...100 version):
double r = ((double)x * 100.0) / 9223372036854775808.0; // 2**63
// main.c
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
// PCH library headers
#include "pcg_variants.h"
#include "entropy.h" // Wrapper around /dev/random
int main(int argc, char** argv)
{
pcg32_random_t rng;
// Seed with external entropy
uint64_t seeds[2];
entropy_getbytes((void*)seeds, sizeof(seeds));
pcg32_srandom_r(&rng, seeds[0], seeds[1]);
for (int i = 0; i < 10; ++i)
{
uint32_t random_unsigned_integer = pcg32_random_r(&rng);
float max = 100.001;
float min = -100.001;
float q = (float)(random_unsigned_integer)/((float)UINT32_MAX)*(max - min) + min;
// Shows 10 float numbers in specified range.
printf("%.6f\n", q);
}
return 0;
}
Compile:
gcc -std=c11 -o pcg_float main.c
I want to generate 100 nodes with random x and y co ordinates. But i do not want to specify any range. Like rand(100) will generate numbers only between 1 to 100. But i want the numbers distributed over a large region and i want them to be random. How can i implement it using C?
i have tried:
int gen_rand_position(void)
{
int i,j,a[100],b[100];
for(i=0,j=0;i<100,j<100;i++,j++)
{
x=rand();
y=rand();
a[i]=x;
b[j]=y;
}
}
This not choosing randomly. Can i have more efficient random function?
You need to have a range otherwise what are you going to do with an infinite number?
With no arguments - rand() will return an integer between 0 and RAND_MAX ( normally 32765).
If you need a number larger than this you could combine two rand() numbers. There are complicated statistical arguments about the best way to combine random numbers so you don't change the randomness but I don't think you need to worry about that.
Edit: since RAND_MAX is (in this case) a 15bit number, to get a 30bit range multiply two rand() together, to get a 32bit range multiply again - it may wrap around but that doesn't change the randomness (significantly).
To obtain a random number distributed over the entire int range, combine the random bits from multiple calls to rand():
#include <stdlib.h>
int large_rand()
{
const int RAND_BITS = 15; /* covers stdc minimum for RAND_MAX */
const int INT_BITS = 8 * sizeof(int);
const int ITERS = (INT_BITS + RAND_BITS - 1) / RAND_BITS;
int i, result = 0;
for (i = 0; i < ITERS; i++) {
result <<= RAND_BITS;
result |= rand() & ~(~0U << RAND_BITS);
}
return result;
}
To get a random number in the desired range, use large_rand() % (MAX + 1), where MAX is the largest number you want to get.