Random float number generation

后端 未结 14 1681
孤城傲影
孤城傲影 2020-11-22 05:05

How do I generate random floats in C++?

I thought I could take the integer rand and divide it by something, would that be adequate enough?

14条回答
  •  清歌不尽
    2020-11-22 05:33

    In my opinion the above answer do give some 'random' float, but none of them is truly a random float (i.e. they miss a part of the float representation). Before I will rush into my implementation lets first have a look at the ANSI/IEEE standard format for floats:

    |sign (1-bit)| e (8-bits) | f (23-bit) |

    the number represented by this word is (-1 * sign) * 2^e * 1.f

    note the the 'e' number is a biased (with a bias of 127) number thus ranging from -127 to 126. The most simple (and actually most random) function is to just write the data of a random int into a float, thus

    int tmp = rand();
    float f = (float)*((float*)&tmp);
    

    note that if you do float f = (float)rand(); it will convert the integer into a float (thus 10 will become 10.0).

    So now if you want to limit the maximum value you can do something like (not sure if this works)

    int tmp = rand();
    float f = *((float*)&tmp);
    tmp = (unsigned int)f       // note float to int conversion!
    tmp %= max_number;
    f -= tmp;
    

    but if you look at the structure of the float you can see that the maximum value of a float is (approx) 2^127 which is way larger as the maximum value of an int (2^32) thus ruling out a significant part of the numbers that can be represented by a float. This is my final implementation:

    /**
     * Function generates a random float using the upper_bound float to determine 
     * the upper bound for the exponent and for the fractional part.
     * @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
     * @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
     * @param sign_flag if sign_flag = 0 the random number is always positive, if 
     *              sign_flag = 1 then the sign bit is random as well
     * @return a random float
     */
    float randf(int min_exp, int max_exp, char sign_flag) {
        assert(min_exp <= max_exp);
    
        int min_exp_mod = min_exp + 126;
    
        int sign_mod = sign_flag + 1;
        int frac_mod = (1 << 23);
    
        int s = rand() % sign_mod;  // note x % 1 = 0
        int e = (rand() % max_exp) + min_exp_mod;
        int f = rand() % frac_mod;
    
        int tmp = (s << 31) | (e << 23) | f;
    
        float r = (float)*((float*)(&tmp));
    
        /** uncomment if you want to see the structure of the float. */
    //    printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);
    
        return r;
    }
    

    using this function randf(0, 8, 0) will return a random number between 0.0 and 255.0

提交回复
热议问题