54

I can't find any solution to generate a random float number in the range of [0,a], where a is some float defined by a user.

I have tried the following, but it doesn't seem to work correctly.

float x=(float)rand()/((float)RAND_MAX/a)
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
fragon
  • 3,391
  • 10
  • 39
  • 76

6 Answers6

78

Try:

float x = (float)rand()/(float)(RAND_MAX/a);

To understand how this works consider the following.

N = a random value in [0..RAND_MAX] inclusively.

The above equation (removing the casts for clarity) becomes:

N/(RAND_MAX/a)

But division by a fraction is the equivalent to multiplying by said fraction's reciprocal, so this is equivalent to:

N * (a/RAND_MAX)

which can be rewritten as:

a * (N/RAND_MAX)

Considering N/RAND_MAX is always a floating point value between 0.0 and 1.0, this will generate a value between 0.0 and a.

Alternatively, you can use the following, which effectively does the breakdown I showed above. I actually prefer this simply because it is clearer what is actually going on (to me, anyway):

float x = ((float)rand()/(float)(RAND_MAX)) * a;

Note: the floating point representation of a must be exact or this will never hit your absolute edge case of a (it will get close). See this article for the gritty details about why.

Sample

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

int main(int argc, char *argv[])
{
    srand((unsigned int)time(NULL));

    float a = 5.0;
    for (int i=0;i<20;i++)
        printf("%f\n", ((float)rand()/(float)(RAND_MAX)) * a);
    return 0;
}

Output

1.625741
3.832026
4.853078
0.687247
0.568085
2.810053
3.561830
3.674827
2.814782
3.047727
3.154944
0.141873
4.464814
0.124696
0.766487
2.349450
2.201889
2.148071
2.624953
2.578719
Foad S. Farimani
  • 12,396
  • 15
  • 78
  • 193
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • 20
    This may have really bad rounding properties. rand() returns a 32-bit int, which you're casting to a 32-bit float, which will cause values to be quantized. For example, it's 64 times more likely that you'll get the value 1000000192 than the value 1, since 1000000161 through 1000000223 all round to 1000000192. You can avoid this by casting to a double instead, then casting down to a float at the end: float((double)rand()/(double)(RAND_MAX/a)). – Glenn Maynard Dec 24 '15 at 23:32
  • 3
    for my mind the cleares form is **a * (N/RAND_MAX)** since ``N/RAND_MAX`` is a random number between 0 and 1. – Zibri Sep 26 '19 at 06:36
  • @GlennMaynard: If you were dividing by `(RAND_MAX+1ULL)` (presumably a power of 2), you'd just be scaling the FP exponent. Some rounding is actually necessary: if you want to generate *uniform* float value over [0..1], but still have a chance to generate every representable float, you need multiple integer values to round to the same final float for the 0.5, 1 part of the range. The smaller the exponent, the closer each representable float is, which is why you can't just use `rand` to generate FP bit-patterns (wouldn't be uniform). – Peter Cordes May 13 '21 at 19:18
  • Unless you only use ~24 bits of entropy so every possible output is evenly spaced (e.g. generate [1,2] and then subtract 1.0), for every 1 time you get a particular really tiny number, you need to get a number in the 0.5, 1 range many times, for the distribution to be uniform. Still, dividing by `RAND_MAX` instead of `RAND_MAX+1` could mean there's some benefit or at least difference from converting rand -> double. (With double, you probably have enough precision to use a multiplicative inverse instead of actual division.) – Peter Cordes May 13 '21 at 19:21
32

You can also generate in a range [min, max] with something like

float float_rand( float min, float max )
{
    float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
    return min + scale * ( max - min );      /* [min, max] */
}
Rob
  • 26,989
  • 16
  • 82
  • 98
baz
  • 1,317
  • 15
  • 10
3

while it might not matter now here is a function which generate a float between 2 values.

#include <math.h>

float func_Uniform(float left, float right) {
    float randomNumber = sin(rand() * rand());
    return left + (right - left) * fabs(randomNumber);
}
  • 2
    Nice trick and the only one which deals with the quantization introduced by scaling a random number € [0..RAND_MAX] € |N. However, the multiplication of two random numbers and the sine leads to a non uniform distribution. Can this somehow be circumvented? https://math.stackexchange.com/questions/456250/probability-distribution-for-product-of-two-random-numbers – Wör Du Schnaffzig May 07 '21 at 11:14
1

This generates a random float between two floats.

float RandomFloat(float min, float max){
   return ((max - min) * ((float)rand() / RAND_MAX)) + min;
}
dreamcrash
  • 47,137
  • 25
  • 94
  • 117
1

If you want to generate a random float in a range, try a next solution.

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


float
random_float(const float min, const float max)
{
    if (max == min) return min;
    else if (min < max) return (max - min) * ((float)rand() / RAND_MAX) + min;

    // return 0 if min > max
    return 0;
}


int
main (const int argc, const char *argv[])
{
    srand(time(NULL));

    char line[] = "-------------------------------------------";

    float data[10][2] = {
        {-10, 10},
        {-5., 5},
        {-1, 1},
        {-0.25, -0.15},
        {1.5, 1.52},
        {-1700, 8000},
        {-0.1, 0.1},
        {-1, 0},
        {-1, -2},
        {1.2, 1.1}
    };

    puts(line);
    puts("     From    |    Result    |      To");
    puts(line);


    int i;
    for (i = 0; i < 10; ++i) {
        printf("%12f | %12f | %12f\n", data[i][0], random_float(data[i][0], data[i][1]), data[i][1]);
    }

    puts(line);

    return 0;
}

A result (values is fickle)

-------------------------------------------
     From    |    Result    |      To
-------------------------------------------
  -10.000000 |     2.330828 |    10.000000
   -5.000000 |    -4.945523 |     5.000000
   -1.000000 |     0.004242 |     1.000000
   -0.250000 |    -0.203197 |    -0.150000
    1.500000 |     1.513431 |     1.520000
-1700.000000 |  3292.941895 |  8000.000000
   -0.100000 |    -0.021541 |     0.100000
   -1.000000 |    -0.148299 |     0.000000
   -1.000000 |     0.000000 |    -2.000000
    1.200000 |     0.000000 |     1.100000
-------------------------------------------
PADYMKO
  • 4,217
  • 2
  • 36
  • 41
-4

Maybe also so: a=Convert.ToDouble rand.Next (-1000,1000))/100; So we can make number from -10,00 to 10,00.