Generate random double number in range [0, 1] in C

前端 未结 2 1638
自闭症患者
自闭症患者 2020-12-12 08:30

I have to generate random double number in between 0 and 1. How can i do this using C? I\'ve tried to generate an integer number between 0 and one million and then divide th

2条回答
  •  粉色の甜心
    2020-12-12 08:45

    generate random double number in between 0 and 1

    Some things to consider:

    Include 1.0??

    I'd expect a goal of "in range [0, 1)" rather than "in range [0, 1]". That inclusion of 1.0 creates complexities as it unbalances the distribution. Let us assume [0, 1).

    rand() Quality

    rand() is of unspecified quality and and its range [0...RAND_MAX] might not end 1 less than a power of two. Let us assume rand() is good enough for now and RAND_MAX is a Mersenne Number (which is very common) to facilitate joining multiple rand() calls with a simple ^.

    Small numbers

    About half of all positive double are less than 1.0. Should all of them have a chance?

    Typicality DBL_MANT_DIG is 53 and so:

    There are 252 double values in the [0.5...1.0) range.
    There are 252 double values in the [0.25...0.5) range.
    There are 252 double values in the [0.125...0.25) range.
    ...

    Do we want a 50% chance of a value from the first group, 25% from the next, 12.5% from the next .... ?

    Or satisfied with:

    Form 253 double values in the [0.0...1.0) range evenly distributed?


    Let us go for the second goal for now - easier to code.

    Generate an whole number double in the range [0...253) and then divide by 253.

    RAND_MAX >= 0x7FFF by definition, so we get at least 15 bits of random bits.

    Below is some illustrative code that, not so efficiently, forms a double [0.0 ... 1.0).

    // Illustrative code
    double rand_double_01(void) {
      unsigned long long r = 0;
      #define RANDOM_BITS 15
      for (int i = 0; i < DBL_MANT_DIG; i += RANDOM_BITS) {
        r <<= RANDOM_BITS;
        r ^= rand();
      }
      r %= 1uLL << DBL_MANT_DIG;   // Mask off lower 53 bits
      double dr = r; // expected conversion is exact
      // scale [0 ... 1.0)
      dr /= 1uLL << DBL_MANT_DIG;  // expected conversion/quotient exact 
      return double dr; 
    }
    

    Note: Above code can fail when DBL_MANT_DIG >= 64 (not common) or FLT_RADIX != 2 (very uncommon).

提交回复
热议问题