Generate random doubles that follow a specific distribution - c

So I have the distribution f(x) = (4-2x)/3, for x in [0,1], and f(x) = 0 elsewhere.
I now want to generate, say n = 100 random numbers from this distribution. I tried to follow this example, and this is my own code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <math.h>
#include <stdlib.h>
//pdf(x) = 1 if x>1
// = 0 if x<0
// = 1/3*(4-2x) otherwise
int N = 10;
int var1(int argc, char **argv) {
int p = 0, i;
for (i = 0; i < N; i++) {
p = (double)(rand() % 100)/100; // Generates 100 numbers in [0,1]
if (p > 1)
printf("%d ", 0);
else if (p < 0)
printf("%d ", 0);
else
printf("%f ", p * (4-2*0.1)/3);
}
printf("...");
return 0;
}
However my output is just zeroes:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 …
I have two questions:
What am I missing?
In the link I provided, why has he replaced x by 0.1? I just did the same thing but I don't understand why.

First, you're not returning the range of random numbers you think you are:
p = (double)(rand() % 100)/100;
The right hand size will give you a number in the range ( 0.00, 0.01, 0.02 ... 0.99 ). But then you assign that value to p, which is of type int. The fractional part is truncated, so the assigned value will always be 0.
Change the type of p to double to store the proper values. Also, if you want a wider range of random values, use this instead:
p = (double)rand() / RAND_MAX;
As for this:
printf("%f ", p * (4-2*0.1)/3);
Compared to the linked code:
printf("%f ", p * 0.1 / 360);
Their code isn't putting 0.1 in place of x. p is the same as x, but for some reason they're adding the extra 0.1 factor.
For you to be doing f(x) = (4-2x)/3, you need this:
printf("%f ", (4-2*p)/3);

Preamble
The function in the question, f(x) = (4-2x)/3 for x in [0, 1], is a probability density function, not a cumulative distribution function. If the distribution were drawn as a curve with unit area between the x axis and the curve, the probability density function is the slope of that curve, while the cumulative distribution function is the amount of area under the curve up to a certain x.
We can see (4-2x)/3 is not a cumulative distribution function because the cumulative distribution must be 1 at the end of the distribution (∞ in general, but 1 here since the function is zero beyond 1, but (4-2x)/3 is 2/3 at 1. We can see it is a probability density function because its integral (shown below) is 1 at the end of the distribution.
The link given in the question uses a cumulative distribution function. In fact, it is a cumulative distribution function for a uniform distribution over [0, 360]. Because of that, solving the necessary equation (see below) is merely a matter of scaling. This is trivial and does not serve as a general example for generating samples for an arbitrary distribution.
Solution
Given a probability density function, f(x), the corresponding cumulative distribution function, F(x), is the integral of f from −∞ to x. We can use the cumulative distribution function to convert a uniform distribution to the desired distribution.
The integral of (4-2x)/3 is (4x−x2)/3 (plus a constant). Since this is zero at x=0 and f(x) is zero for x < 0, F(x) is also (4x−x2)/3 in [0, 1].
If we have a sample p from a uniform distribution in [0, 1], the point x where the amount of the desired distribution at or below x equals the amount of the uniform distribution at or below p satisfies F(x) = p.
Thus (4x−x2)/3 = p, so x = 2 + sqrt(4−3p).
Thus, given p generated with p = (double) rand() / RAND_MAX, we can find the sample for the desired distribution as 2 + sqrt(4-3*p).

Related

How to generate mxn matrix with randomly generated 0 and 1 with probability in C

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;

Comparing the ratio of two values to 1

I'm working via a basic 'Programming in C' book.
I have written the following code based off of it in order to calculate the square root of a number:
#include <stdio.h>
float absoluteValue (float x)
{
if(x < 0)
x = -x;
return (x);
}
float squareRoot (float x, float epsilon)
{
float guess = 1.0;
while(absoluteValue(guess * guess - x) >= epsilon)
{
guess = (x/guess + guess) / 2.0;
}
return guess;
}
int main (void)
{
printf("SquareRoot(2.0) = %f\n", squareRoot(2.0, .00001));
printf("SquareRoot(144.0) = %f\n", squareRoot(144.0, .00001));
printf("SquareRoot(17.5) = %f\n", squareRoot(17.5, .00001));
return 0;
}
An exercise in the book has said that the current criteria used for termination of the loop in squareRoot() is not suitable for use when computing the square root of a very large or a very small number.
Instead of comparing the difference between the value of x and the value of guess^2, the program should compare the ratio of the two values to 1. The closer this ratio gets to 1, the more accurate the approximation of the square root.
If the ratio is just guess^2/x, shouldn't my code inside of the while loop:
guess = (x/guess + guess) / 2.0;
be replaced by:
guess = ((guess * guess) / x ) / 1 ; ?
This compiles but nothing is printed out into the terminal. Surely I'm doing exactly what the exercise is asking?
To calculate the ratio just do (guess * guess / x) that could be either higher or lower than 1 depending on your implementation. Similarly, your margin of error (in percent) would be absoluteValue((guess * guess / x) - 1) * 100
All they want you to check is how close the square root is. By squaring the number you get and dividing it by the number you took the square root of you are just checking how close you were to the original number.
Example:
sqrt(4) = 2
2 * 2 / 4 = 1 (this is exact so we get 1 (2 * 2 = 4 = 4))
margin of error = (1 - 1) * 100 = 0% margin of error
Another example:
sqrt(4) = 1.999 (lets just say you got this)
1.999 * 1.999 = 3.996
3.996/4 = .999 (so we are close but not exact)
To check margin of error:
.999 - 1 = -.001
absoluteValue(-.001) = .001
.001 * 100 = .1% margin of error
How about applying a little algebra? Your current criterion is:
|guess2 - x| >= epsilon
You are elsewhere assuming that guess is nonzero, so it is algebraically safe to convert that to
|1 - x / guess2| >= epsilon / guess2
epsilon is just a parameter governing how close the match needs to be, and the above reformulation shows that it must be expressed in terms of the floating-point spacing near guess2 to yield equivalent precision for all evaluations. But of course that's not possible because epsilon is a constant. This is, in fact, exactly why the original criterion gets less effective as x diverges from 1.
Let us instead write the alternative expression
|1 - x / guess2| >= delta
Here, delta expresses the desired precision in terms of the spacing of floating point values in the vicinity of 1, which is related to a fixed quantity sometimes called the "machine epsilon". You can directly select the required precision via your choice of delta, and you will get the same precision for all x, provided that no arithmetic operations overflow.
Now just convert that back into code.
Suggest a different point of view.
As this method guess_next = (x/guess + guess) / 2.0;, once the initial approximation is in the neighborhood, the number of bits of accuracy doubles. Example log2(FLT_EPSILON) is about -23, so 6 iterations are needed. (Think 23, 12, 6, 3, 2, 1)
The trouble with using guess * guess is that it may vanish, become 0.0 or infinity for a non-zero x.
To form a quality initial guess:
assert(x > 0.0f);
int expo;
float signif = frexpf(x, &expo);
float guess = ldexpf(signif, expo/2);
Now iterate N times (e.g. 6), (N based on FLT_EPSILON, FLT_DECIMAL_DIG or FLT_DIG.)
for (i=0; i<N; i++) {
guess = (x/guess + guess) / 2.0f;
}
The cost of perhaps an extra iteration is saved by avoiding an expensive termination condition calculation.
If code wants to compare a/b nearest to 1.0f
Simply use some epsilon factor like 1 or 2.
float a = guess;
float b = x/guess;
assert(b);
float q = a/b;
#define FACTOR (1.0f /* some value 1.0f to maybe 2,3 or 4 */)
if (q >= 1.0f - FLT_EPSILON*N && q <= 1.0f + FLT_EPSILON*N) {
close_enough();
}
First lesson in numerical analysis: for floating point numbers x+y has the potential for large relative errors, especially when the sum is near zero, but x*y has very limited relative errors.

taylor series with error at most 10^-3

I'm trying to calculate the the taylor series of cos(x) with error at most 10^-3 and for all x ∈ [-pi/4, pi/4], that means my error needs to be less than 0.001. I can modify the x +=in the for loop to have different result. I tried several numbers but it never turns to an error less than 0.001.
#include <stdio.h>
#include <math.h>
float cosine(float x, int j)
{
float val = 1;
for (int k = j - 1; k >= 0; --k)
val = 1 - x*x/(2*k+2)/(2*k+1)*val;
return val;
}
int main( void )
{
for( double x = 0; x <= PI/4; x += 0.9999 )
{
if(cosine(x, 2) <= 0.001)
{
printf("cos(x) : %10g %10g %10g\n", x, cos(x), cosine(x, 2));
}
printf("cos(x) : %10g %10g %10g\n", x, cos(x), cosine(x, 2));
}
return 0;
}
I'm also doing this for e^x too. For this part, x must in [-2,2] .
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int i = n - 1; i > 0; --i )
sum = 1 + x * sum / i;
return sum;
}
int main( void )
{
// change the number of x in for loop so you can have different range
for( float x = -2.0f; x <= 2.0f; x += 1.587 )
{
// change the frist parameter to have different n value
if(exponential(5, x) <= 0.001)
{
printf("e^x = %f\n", exponential(5, x));
}
printf("e^x = %f\n", exponential(5, x));
}
return 0;
}
But whenever I changed the number of terms in the for loop, it always have an error that is greater than 1. How am I suppose to change it to have errors less than 10^-3?
Thanks!
My understanding is that to increase precision, you would need to consider more terms in the Taylor series. For example, consider what happens when
you attempt to calculate e(1) by a Taylor series.
$e(x) = \sum\limits_{n=0}^{\infty} frac{x^n}{n!}$
we can consider the first few terms in the expansion of e(1):
n value of nth term sum
0 x^0/0! = 1 1
1 x^1/1! = 1 2
2 x^2/2! = 0.5 2.5
3 x^3/3! = 0.16667 2.66667
4 x^4/4! = 0.04167 2.70834
You should notice two things, first that as we add more terms we are getting closer to the exact value of e(1), also that the difference between consecutive sums are getting smaller.
So, an implementation of e(x) could be written as:
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
typedef float (*term)(int, int);
float evalSum(int, int, int, term);
float expTerm(int, int);
int fact(int);
int mypow(int, int);
bool sgn(float);
const int maxTerm = 10; // number of terms to evaluate in series
const float epsilon = 0.001; // the accepted error
int main(void)
{
// change these values to modify the range and increment
float start = -2;
float end = 2;
float inc = 1;
for(int x = start; x <= end; x += inc)
{
float value = 0;
float prev = 0;
for(int ndx = 0; ndx < maxTerm; ndx++)
{
value = evalSum(0, ndx, x, expTerm);
float diff = fabs(value-prev);
if((sgn(value) && sgn(prev)) && (diff < epsilon))
break;
else
prev = value;
}
printf("the approximate value of exp(%d) is %f\n", x, value);
}
return 0;
}
I've used as a guess that we will not need to use more then ten terms in the expansion to get to the desired precision, thus the inner for loop is where we loop over values of n in the range [0,10].
Also, we have several lines dedicated to checking if we reach the required precision. First I calculate the absolute value of the difference between the current evaluation and the previous evaluation, and take the absolute difference. Checking if the difference is less than our epsilon value (1E-3) is on of the criteria to exit the loop early. I also needed to check that the sign of of the current and the previous values were the same due to some fluctuation in calculating the value of e(-1), that is what the first clause in the conditional is doing.
float evalSum(int start, int end, int val, term fnct)
{
float sum = 0;
for(int n = start; n <= end; n++)
{
sum += fnct(n, val);
}
return sum;
}
This is a utility function that I wrote to evaluate the first n-terms of a series. start is the starting value (which is this code always 0), and end is the ending value. The final parameter is a pointer to a function that represents how to calculate a given term. In this code, fnct can be a pointer to any function that takes to integer parameters and returns a float.
float expTerm(int n, int x)
{
return (float)mypow(x,n)/(float)fact(n);
}
Buried down in this one-line function is where most of the work happens. This function represents the closed form of a Taylor expansion for e(n). Looking carefully at the above, you should be able to see that we are calculating $\fract{x^n}{n!}$ for a given value of x and n. As a hint, for doing the cosine part you would need to create a function to evaluate the closed for a term in the Taylor expansion of cos. This is given by $(-1)^n\fact{x^{2n}}{(2n)!}$.
int fact(int n)
{
if(0 == n)
return 1; // by defination
else if(1 == n)
return 1;
else
return n*fact(n-1);
}
This is just a standard implementation of the factorial function. Nothing special to see here.
int mypow(int base, int exp)
{
int result = 1;
while(exp)
{
if(exp&1) // b&1 quick check for odd power
{
result *= base;
}
exp >>=1; // exp >>= 1 quick division by 2
base *= base;
}
return result;
}
A custom function for doing exponentiation. We certainly could have used the version from <math.h>, but because I knew we would only be doing integer powers we could write an optimized version. Hint: in doing cosine you probably will need to use the version from <math.h> to work with floating point bases.
bool sgn(float x)
{
if(x < 0) return false;
else return true;
}
An incredibly simple function to determine the sign of a floating point value, returning true is positive and false otherwise.
This code was compiled on my Ubuntu-14.04 using gcc version 4.8.4:
******#crossbow:~/personal/projects$ gcc -std=c99 -pedantic -Wall series.c -o series
******#crossbow:~/personal/projects$ ./series
the approximate value of exp(-2) is 0.135097
the approximate value of exp(-1) is 0.367857
the approximate value of exp(0) is 1.000000
the approximate value of exp(1) is 2.718254
the approximate value of exp(2) is 7.388713
The expected values, as given by using bc are:
******#crossbow:~$ bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
e(-2)
.13533528323661269189
e(-1)
.36787944117144232159
e(0)
1.00000000000000000000
e(1)
2.71828182845904523536
e(2)
7.38905609893065022723
As you can see, the values are well within the tolerances that you requests. I leave it as an exercise to do the cosine part.
Hope this helps,
-T
exp and cos have power series that converge everywhere on the real line. For any bounded interval, e.g. [-pi/4, pi/4] or [-2, 2], the power series converge not just pointwise, but uniformly to exp and cos.
Pointwise convergence means that for any x in the region, and any epsilon > 0, you can pick a large enough N so that the approximation you get from the first N terms of the taylor series is within epsilon of the true value. However, with pointwise convergence, the N may be small for some x's and large for others, and since there are infinitely many x's there may be no finite N that accommodates them all. For some functions that really is what happens sometimes.
Uniform convergence means that for any epsilon > 0, you can pick a large enough N so that the approximation is within epsilon for EVERY x in the region. That's the kind of approximation that you are looking for, and you are guaranteed that that's the kind of convergence that you have.
In principle you could look at one of the proofs that exp, cos are uniformly convergent on any finite domain, sit down and say "what if we take epsilon = .001, and the regions to be ...", and compute some finite bound on N using a pen and paper. However most of these proofs will use at some steps some estimates that aren't sharp, so the value of N that you compute will be larger than necessary -- maybe a lot larger. It would be simpler to just implement it for N being a variable, then check the values using a for-loop like you did in your code, and see how large you have to make it so that the error is less than .001 everywhere.
So, I can't tell what the right value of N you need to pick is, but the math guarantees that if you keep trying larger values eventually you will find one that works.

Generating random number within Cuda kernel in a varying range

I am trying to generate random number random numbers within the cuda kernel. I wish to generate the random numbers from uniform distribution and in the integer form, starting from 1 up to 8. The random numbers would be different for each of the threads. The range up to which random number can be generated would also vary from one thread to another. The maximum of the range in one thread might be as low as 2 or in the other thread it can be high as 8, but not higher than that. So, I am providing an example below of how I want the numbers to get generated :
In thread#1 --> maximum of the range is 2 and so the random number should be between 1 and 2
In thread#2 --> maximum of the range is 6 and so the random number should be between 1 and 6
In thread#3 --> maximum of the range is 5 and so the random number should be between 1 and 5
and so on...
EDIT: I've edited my answer to fix some of the deficiencies pointed out in the other answers (#tudorturcu) and comments.
Use CURAND to generate a uniform
distribution
between 0.0 and 1.0. Note: 1.0 is included and 0.0 is excluded
Then multiply this by the desired range (largest value - smallest
value + 0.999999).
Then add the offset (+ smallest value).
Then truncate to an integer.
Something like this in your device code:
int idx = threadIdx.x+blockDim.x*blockIdx.x;
// assume have already set up curand and generated state for each thread...
// assume ranges vary by thread index
float myrandf = curand_uniform(&(my_curandstate[idx]));
myrandf *= (max_rand_int[idx] - min_rand_int[idx] + 0.999999);
myrandf += min_rand_int[idx];
int myrand = (int)truncf(myrandf);
You should:
#include <math.h>
for truncf
Here's a fully worked example:
$ cat t527.cu
#include <stdio.h>
#include <curand.h>
#include <curand_kernel.h>
#include <math.h>
#include <assert.h>
#define MIN 2
#define MAX 7
#define ITER 10000000
__global__ void setup_kernel(curandState *state){
int idx = threadIdx.x+blockDim.x*blockIdx.x;
curand_init(1234, idx, 0, &state[idx]);
}
__global__ void generate_kernel(curandState *my_curandstate, const unsigned int n, const unsigned *max_rand_int, const unsigned *min_rand_int, unsigned int *result){
int idx = threadIdx.x + blockDim.x*blockIdx.x;
int count = 0;
while (count < n){
float myrandf = curand_uniform(my_curandstate+idx);
myrandf *= (max_rand_int[idx] - min_rand_int[idx]+0.999999);
myrandf += min_rand_int[idx];
int myrand = (int)truncf(myrandf);
assert(myrand <= max_rand_int[idx]);
assert(myrand >= min_rand_int[idx]);
result[myrand-min_rand_int[idx]]++;
count++;}
}
int main(){
curandState *d_state;
cudaMalloc(&d_state, sizeof(curandState));
unsigned *d_result, *h_result;
unsigned *d_max_rand_int, *h_max_rand_int, *d_min_rand_int, *h_min_rand_int;
cudaMalloc(&d_result, (MAX-MIN+1) * sizeof(unsigned));
h_result = (unsigned *)malloc((MAX-MIN+1)*sizeof(unsigned));
cudaMalloc(&d_max_rand_int, sizeof(unsigned));
h_max_rand_int = (unsigned *)malloc(sizeof(unsigned));
cudaMalloc(&d_min_rand_int, sizeof(unsigned));
h_min_rand_int = (unsigned *)malloc(sizeof(unsigned));
cudaMemset(d_result, 0, (MAX-MIN+1)*sizeof(unsigned));
setup_kernel<<<1,1>>>(d_state);
*h_max_rand_int = MAX;
*h_min_rand_int = MIN;
cudaMemcpy(d_max_rand_int, h_max_rand_int, sizeof(unsigned), cudaMemcpyHostToDevice);
cudaMemcpy(d_min_rand_int, h_min_rand_int, sizeof(unsigned), cudaMemcpyHostToDevice);
generate_kernel<<<1,1>>>(d_state, ITER, d_max_rand_int, d_min_rand_int, d_result);
cudaMemcpy(h_result, d_result, (MAX-MIN+1) * sizeof(unsigned), cudaMemcpyDeviceToHost);
printf("Bin: Count: \n");
for (int i = MIN; i <= MAX; i++)
printf("%d %d\n", i, h_result[i-MIN]);
return 0;
}
$ nvcc -arch=sm_20 -o t527 t527.cu -lcurand
$ cuda-memcheck ./t527
========= CUDA-MEMCHECK
Bin: Count:
2 1665496
3 1668130
4 1667644
5 1667435
6 1665026
7 1666269
========= ERROR SUMMARY: 0 errors
$
#Robert's example doesn't generate a perfectly uniform distribution (although all the numbers in the range are generated and all the generated numbers are in the range). Both the smallest and largest value have 0.5 the probability of being chosen of the rest of the numbers in the range.
At step 2, you should multiply with the number of values in the range: (largest value - smallest value + 0.999999). *
At step 3, the offset should be (+ smallest value) instead of (+ smallest value + 0.5).
Steps 1 and 4 remain the same.
*As #Kamil Czerski noted, 1.0 is included in the distribution. Adding 1.0 instead of 0.99999 would sometimes result in a number outside of the desired range.
For a safer general purpose random integer function using curand_uniform() that can handle larger integers:
#include <math.h>
int rand = (int)(ceil((curand_uniform(&state)*(RANGE + 1))) - 1);
Multiple your float by RANGE + 1 then take the ceiling, subtract by 1, and cast as an integer. Taking the ceiling produces a whole number between 1 and RANGE + 1 so when we subtract by one we get an integer between 0 and RANGE.
Addition discussion:
If 0.0 were included in curand_uniform() and 1.0 were not then,
(int)((curand_uniform(&state)*(RANGE + 1)));
would produce an integer between 0 and RANGE. We are safe truncating to an integer because RANGE + 1 is not a possible result. We are also happy because the distribution includes our entire range.
Since 0.0 is excluded and 1.0 included then all possible results need to be shifted down by some amount to truncate to an integer safely. This is accomplished by adding .999999 to RANGE and multiplying.
(int)((curand_uniform(&state)*(RANGE + .999999)))
The solution is not perfect however because not all possible values between 0 and RANGE are represented (not considering 0 or RANGE). This produces a slight bias against the greatest integer in our range.
The greatest offset according to IEEE 754 Floating Point is .999999940395355224609375 as this would be the largest decimal less than one before the computer rounds up. The problem with using this value is that the computer will start rounding up for values greater than 1 when the decimal part exceeds approximately .999999. In fact, our offset must shrink in proportion to the value of our integer because the integer part takes up more space in memory. For integers greater than 10000000 you would have to amend the solution since virtually all decimal parts will round up.

Generate Float Random Values (also negative)

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

Resources