321

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?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
hasen
  • 161,647
  • 65
  • 194
  • 231
  • 2
    It depends rather what you want the number for, and how random. typically rand() will give 15 bits of randomness, but floats have 23 bit precision, so it will miss some values out. – Pete Kirkham Mar 26 '09 at 16:11
  • 2
    I have updated my answer to include all the major options available and my choice to focus on `random` header added in C++11 is further bolstered by the standard document [N3924: Discouraging rand() in C++14](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3924.pdf). I include `rand()` in my answer for mostly historical considerations but also realizing legacy application do exist. – Shafik Yaghmour Jun 17 '14 at 14:12
  • 1
    My answer includes how to avoid getting the same numbers every time with the `` header – Andreas DM Apr 10 '16 at 07:52

14 Answers14

444

rand() can be used to generate pseudo-random numbers in C++. In combination with RAND_MAX and a little math, you can generate random numbers in any arbitrary interval you choose. This is sufficient for learning purposes and toy programs. If you need truly random numbers with normal distribution, you'll need to employ a more advanced method.


This will generate a number from 0.0 to 1.0, inclusive.

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

This will generate a number from 0.0 to some arbitrary float, X:

float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));

This will generate a number from some arbitrary LO to some arbitrary HI:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

Note that the rand() function will often not be sufficient if you need truly random numbers.


Before calling rand(), you must first "seed" the random number generator by calling srand(). This should be done once during your program's run -- not once every time you call rand(). This is often done like this:

srand (static_cast <unsigned> (time(0)));

In order to call rand or srand you must #include <cstdlib>.

In order to call time, you must #include <ctime>.

Florin Mircea
  • 966
  • 12
  • 24
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • 27
    Don't forget to seed first! – Klaim Mar 26 '09 at 16:18
  • 15
    Best to note that the both limits are inclusive. – dmckee --- ex-moderator kitten Mar 26 '09 at 16:52
  • Also the system rand() is usually fairly primitive, and not a good idea for many applications---look at the many SO questions on random number generators for details... – dmckee --- ex-moderator kitten Mar 26 '09 at 16:53
  • What about NaN if you cast from `int`? – Reactormonk Sep 05 '12 at 19:47
  • @JohnDibling Reverse `double a = 0.0/0.0; int x = (int) a; printf("%i", x)`. – Reactormonk Sep 06 '12 at 18:12
  • @Tass: I don't see the relevance to the posted question? – John Dibling Sep 25 '12 at 19:07
  • @JohnDibling if you have the bit pattern for `NaN` in an `int`, your random function will return you a `NaN`. – Reactormonk Sep 26 '12 at 22:49
  • Oh you mean in 'X' for example? – John Dibling Sep 27 '12 at 02:35
  • 2
    This is C++, so you'd rather use `` instead. – David G Oct 26 '12 at 14:27
  • 3
    What is the reason for choosing to divide from the denominator instead of multiply by the result of the division? – Nick Larsen Dec 09 '12 at 01:02
  • @NickLarsen That's what I was wondering. Especially since division is more expensive than multiplication... isn't it? – Cam Jackson Jan 29 '13 at 00:14
  • 15
    This answer is misleading. It was covered at Going Native 2013 last week; rand() Considered Harmful, http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful for a very detailed explanation. – Ade Miller Sep 08 '13 at 00:13
  • 7
    @AdeMiller: its not misleading, to say nothing of being "plain wrong." I explicitly say that rand is insufficient if you need truly random numbers. the question was asked in terms of *basic understanding*, and it is in that context the answer was provided. yhere is nothng wrong with using rand when learning how to program or in toy projects. – John Dibling Sep 08 '13 at 02:37
  • The distribution is not uniform but same as `rand()`'s: "one of the `k/RAND_MAX`" (for the 1st code sample). – ivan_pozdeev Oct 24 '13 at 19:42
  • @ivan_pozdeev: That's why I state "rand() function will often not be sufficient if you need truly random numbers." – John Dibling Oct 24 '13 at 19:49
  • Wouldn't it be better to use `static_cast` instead of C-style casts? Of course it's not necessary, but IMO it encourages good style for every new programmers reading this answer. – Timo Türschmann Nov 11 '13 at 15:08
  • @TimoTürschmann: It would be. I didn't here because A) in this case a C-style cast *is* a `static_cast` (eg, a conversion) and B) I wanted to keep the examples brief. – John Dibling Nov 11 '13 at 15:15
  • 21
    I dont understand why so many people upvoted this answer. It is mathematically incorrect. RAND_MAX is a very small number (typically 2^16). That means that from 23 bits of the floating point you make only 15 random. The others will be probably zero. You will indeed get random numbers in uniform distribution but of low precision. For example your random generator can generate 0.00001 and 0.00002 but cannot generate 0.000017. So you have a uniform distribution but of low precision (256 times less precision than the actual floating point). – DanielHsH Aug 14 '14 at 08:25
  • 16
    @DanielHsH: The OP specifically asked what mechanics could be used to generate random floats with `rand()`. This question, and my answer, was specifically focused on learning the basics and wasn't concerned about high degrees of precision. You have to learn to walk before you can learn to run. – John Dibling Aug 14 '14 at 12:22
  • There are lots of non-toy, non-learning programs for which the randomness of rand() and random() is perfectly sufficient, e.g. when you just need to ensure that instances of a program or part don't all try to use the same sequence, these functions can be used to expand a little bit of entropy into a unique(ish) sequence. – Britton Kerin Mar 27 '17 at 22:51
  • For reasons why the "toy code" justification is seen as insufficient by some, see p3 of WG21 N3551 (referred to by @shafik-yaghmour). The author refers to the manipulation of the raw output of the engine as an anti-pattern. "Even in the rare cases that an engine’s output actually happens to match a desired distribution, the absence of an explicit distribution forces each future reader of the code to expend mental energy verifying application correctness despite such an obvious lack." – chb May 13 '19 at 06:40
  • To those who think this answer isn't good because it's non-uniform, I just profiled my code and realised that the std::uniform_int_distribution was causing a bottle-neck. Replacing it with mt19937 and code similar to above caused a decrease of two-thirds in my run time!! and it wasn't even part of my inner complexity, so I wasn't looking there. Its seems that the std::uniform[...] is super, super slow, so only use it if you really need it. – Elliott Feb 25 '20 at 07:10
  • 1
    Note: From C++11 on, you should no longer generate random numbers this way. Use the safer and more convenient [random](https://en.cppreference.com/w/cpp/header/random) module instead. – Alex Apr 13 '20 at 12:40
  • Please define "truly random". – Niko O Feb 21 '22 at 12:15
  • I don't see how that will benefit users who are helped by this answer. – John Dibling Mar 04 '22 at 14:12
174

C++11 gives you a lot of new options with random. The canonical paper on this topic would be N3551, Random Number Generation in C++11

To see why using rand() can be problematic see the rand() Considered Harmful presentation material by Stephan T. Lavavej given during the GoingNative 2013 event. The slides are in the comments but here is a direct link.

I also cover boost as well as using rand since legacy code may still require its support.

The example below is distilled from the cppreference site and uses the std::mersenne_twister_engine engine and the std::uniform_real_distribution which generates numbers in the [0,10) interval, with other engines and distributions commented out (see it live):

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;

    //
    // Engines 
    //
    std::mt19937 e2(rd());
    //std::knuth_b e2(rd());
    //std::default_random_engine e2(rd()) ;

    //
    // Distribtuions
    //
    std::uniform_real_distribution<> dist(0, 10);
    //std::normal_distribution<> dist(2, 2);
    //std::student_t_distribution<> dist(5);
    //std::poisson_distribution<> dist(2);
    //std::extreme_value_distribution<> dist(0,2);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(e2))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

output will be similar to the following:

0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****

The output will vary depending on which distribution you choose, so if we decided to go with std::normal_distribution with a value of 2 for both mean and stddev e.g. dist(2, 2) instead the output would be similar to this (see it live):

-6 
-5 
-4 
-3 
-2 **
-1 ****
 0 *******
 1 *********
 2 *********
 3 *******
 4 ****
 5 **
 6 
 7 
 8 
 9 

The following is a modified version of some of the code presented in N3551 (see it live) :

#include <algorithm>
#include <array>
#include <iostream>
#include <random>

std::default_random_engine & global_urng( )
{
    static std::default_random_engine u{};
    return u ;
}

void randomize( )
{
    static std::random_device rd{};
    global_urng().seed( rd() );
}

int main( )
{
  // Manufacture a deck of cards:
  using card = int;
  std::array<card,52> deck{};
  std::iota(deck.begin(), deck.end(), 0);
 
  randomize( ) ;  
    
  std::shuffle(deck.begin(), deck.end(), global_urng());
  // Display each card in the shuffled deck:
  auto suit = []( card c ) { return "SHDC"[c / 13]; };
  auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };
 
  for( card c : deck )
      std::cout << ' ' << rank(c) << suit(c);
 
   std::cout << std::endl;
}

Results will look similar to:

5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S

Boost

Of course Boost.Random is always an option as well, here I am using boost::random::uniform_real_distribution:

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

int main()
{
    boost::random::mt19937 gen;
    boost::random::uniform_real_distribution<> dist(0, 10);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(gen))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

rand()

If you must use rand() then we can go to the C FAQ for a guides on How can I generate floating-point random numbers? , which basically gives an example similar to this for generating an on the interval [0,1):

#include <stdlib.h>

double randZeroToOne()
{
    return rand() / (RAND_MAX + 1.);
}

and to generate a random number in the range from [M,N):

double randMToN(double M, double N)
{
    return M + (rand() / ( RAND_MAX / (N-M) ) ) ;  
}
ari
  • 4,269
  • 5
  • 24
  • 33
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • 1
    can you fix your `randMToN` pls? either note that it's `[M,N]` or add back the `+ 1.` from the above `randZeroToOne`. -> think of calling it like this: `randMToN(0.0, 1.0);` – BeyelerStudios Apr 01 '16 at 07:51
  • 1
    Also be careful with division by zero at `(N-M)`. A nice way to deal with this error is found here: https://stackoverflow.com/questions/33058848/generate-a-random-double-between-1-and-1/50539103#50539103 – DrBeco May 26 '18 at 04:42
  • If anyone cares to see how it is implemented in the standard library, and why it gives better values than the naive division, see here: https://github.com/microsoft/STL/blob/568a21bec058291e551e05b87233b37dd54e9112/stl/inc/random#L242 – Azmisov Dec 19 '21 at 07:06
68

Take a look at Boost.Random. You could do something like this:

float gen_random_float(float min, float max)
{
    boost::mt19937 rng;
    boost::uniform_real<float> u(min, max);
    boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
    return gen();
}

Play around, you might do better passing the same mt19937 object around instead of constructing a new one every time, but hopefully you get the idea.

rlbond
  • 65,341
  • 56
  • 178
  • 228
  • 1
    uniform_real uses a half-open interval [min, max), which means you will get your minimum value but will never reach the maximum value. It's something to consider, although if you round in some way, you can get over this problem. – Signal Jun 17 '11 at 17:09
  • 22
    This is now part of C++11. – Tomas Andrle Nov 26 '11 at 20:23
  • @Wolf in practical applications the odds of hitting any specific floating point value is so low that it doesn't matter if the endpoint is included or excluded. If you need `max` but can use an open-ended `min`, you can reverse the interval easily: `return min + max - gen();`. – Mark Ransom Mar 19 '15 at 21:22
51

In modern c++ you may use the <random> header that came with c++11.
To get random float's you can use std::uniform_real_distribution<>.

You can use a function to generate the numbers and if you don't want the numbers to be the same all the time, set the engine and distribution to be static.
Example:

float get_random()
{
    static std::default_random_engine e;
    static std::uniform_real_distribution<> dis(0, 1); // range [0, 1)
    return dis(e);
}

It's ideal to place the float's in a container such as std::vector:

int main()
{
    std::vector<float> nums;
    for (int i{}; i != 5; ++i) // Generate 5 random floats
        nums.emplace_back(get_random());

    for (const auto& i : nums) std::cout << i << " ";
}

Example output:

0.0518757 0.969106 0.0985112 0.0895674 0.895542
paleonix
  • 2,293
  • 1
  • 13
  • 29
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
  • 1
    `std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1` is technically incorrect, 1.0 will never be generated, see http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution `To create a distribution over the closed interval [a,b], std::nextafter(b, std::numeric_limits::max()) may be used as the second parameter.` – Troyseph Mar 12 '20 at 08:43
  • 7
    This should be the accepted answer, it's freaking 2020. – Alex Apr 13 '20 at 12:41
34

Call the code with two float values, the code works in any range.

float rand_FloatRange(float a, float b)
{
    return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}
Ziezi
  • 6,375
  • 3
  • 39
  • 49
Ivan Prodanov
  • 34,634
  • 78
  • 176
  • 248
  • 1
    It might be worth mentioning that this is a potential use case for `fmaf()` (or the float `fma()` overload in C++) in C99 or C++11, which might preserve more precision. As in, `fmaf((float)rand() / RAND_MAX, b - a, a)`. – Tim Čas Aug 09 '17 at 01:14
  • This works, but note that it introduces a (very) small bias in the results. See here for more info (your method is the "FP Multiply (Biased)" one): https://www.pcg-random.org/posts/bounded-rands.html – Venryx Feb 25 '21 at 09:35
  • Adding to @Venryx, there is apparantly an entire paper on this topic: https://hal.archives-ouvertes.fr/hal-03282794/document. Mundane as it is, this is not really a solved issue! – Mingye Wang Sep 03 '21 at 16:47
22

If you are using C++ and not C, then remember that in technical report 1 (TR1) and in the C++0x draft they have added facilities for a random number generator in the header file, I believe it is identical to the Boost.Random library and definitely more flexible and "modern" than the C library function, rand.

This syntax offers the ability to choose a generator (like the mersenne twister mt19937) and then choose a distribution (normal, bernoulli, binomial etc.).

Syntax is as follows (shameless borrowed from this site):

  #include <iostream>
  #include <random>

  ...

  std::tr1::mt19937 eng;  // a core engine class 
  std::tr1::normal_distribution<float> dist;     

  for (int i = 0; i < 10; ++i)        
      std::cout << dist(eng) << std::endl;
Rick
  • 3,285
  • 17
  • 17
  • 2
    This is now in C++11, also dist can be initialized with a min and max values. – Étienne Jun 06 '15 at 16:11
  • It seems odd to me to put the min and max in the initializer and provide the generator when getting a value - I would prefer if it were the other way around, oh well. – yoyo Dec 13 '19 at 19:45
6

On some systems (Windows with VC springs to mind, currently), RAND_MAX is ridiculously small, i. e. only 15 bit. When dividing by RAND_MAX you are only generating a mantissa of 15 bit instead of the 23 possible bits. This may or may not be a problem for you, but you're missing out some values in that case.

Oh, just noticed that there was already a comment for that problem. Anyway, here's some code that might solve this for you:

float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);

Untested, but might work :-)

Joey
  • 344,408
  • 85
  • 689
  • 683
  • What about float r = (float)((rand() << 9) | rand()) / RAND_MAX? (also untested) – Trap Mar 26 '09 at 17:44
  • Argh, sorry, dividing by RAND_MAX won't take you anywhere ... the whole point of this trick was to have something that's larger than RAND_MAX ... fixed that for me as well. – Joey Mar 27 '09 at 08:07
  • 2
    Be careful about composing random numbers without theory... consecutive calls to rand() might not be completely independent. Hint: if its a linear congruential generator, watch the low bit on consecutive calls: it alternates between 0 and 1. – RBerteig Mar 27 '09 at 08:14
  • I know. For some applications this might be enough, though. But yes, you should probably use more than just two calls in this case. There is no silver bullet in this case, you can't even rely on it being an LCG. Other PRNGs have weak high bits. The Boost solution should be the best here. – Joey Mar 27 '09 at 08:46
  • (nb: The low bit returned by rand in MSVC isn't the lowest bit of the RNG state. For 100 rand() calls I get the following: 1100100000111111101010010010011010101110110110111010011111100100000000010100011011000000100101100011. Java uses a 48-bit LCG and only uses 32 bits, VC seems to do it similarly) – Joey Mar 27 '09 at 08:51
4

drand48(3) is the POSIX standard way. GLibC also provides a reentrant version, drand48_r(3).

The function was declared obsolete in SVID 3 but no adequate alternative was provided so IEEE Std 1003.1-2013 still includes it and has no notes that it's going anywhere anytime soon.

In Windows, the standard way is CryptGenRandom().

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
2

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

user2546926
  • 385
  • 3
  • 12
  • 1
    you have a mistake. rand() % frac_mod willnot work since MAX_RAND is usually lower than (1<<23). – DanielHsH Jul 10 '13 at 08:45
  • I have to admit that I don't know the exact size of MAX_RAND. Never the less it will still work, its maybe a useless statement, but it will still work. 8 % 10 = 8 so thats fine, but if MAX_RAND is always smaller then (1 << 23) you can indeed remove it. – user2546926 Jul 16 '13 at 19:34
  • 2
    No, You are a bit wrong. RandMax is typically ~65,000. That means that from 23 bits you make only 15 random. The others will be probably zero. You will indeed get random numbers but of low precision. For example your random generator can generate 0.001 and 0.002 but cannot generate 0.0017. So you have a uniform distribution but of low precision (256 times less precision than the float). – DanielHsH Jul 17 '13 at 07:37
  • There are two mistakes in this answer. Fixing the exponent range: `int e = (rand() % (max_exp - min_exp)) + min_exp_mod;` and the mantissa: `int f = (int)(frac_mod * (float)rand() / RAND_MAX);` replacing their respective lines above. Note that the mantissa mistake is major: for `RAND_MAX` smaller `1 << 23` you'd only randomise the lower significant bits and get 0s for the most significant bits all the time! – BeyelerStudios Apr 01 '16 at 08:42
2

I wasn't satisfied by any of the answers so far so I wrote a new random float function. It makes bitwise assumptions about the float data type. It still needs a rand() function with at least 15 random bits.

//Returns a random number in the range [0.0f, 1.0f).  Every
//bit of the mantissa is randomized.
float rnd(void){
  //Generate a random number in the range [0.5f, 1.0f).
  unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand()));
  unsigned short coinFlips;

  //If the coin is tails, return the number, otherwise
  //divide the random number by two by decrementing the
  //exponent and keep going. The exponent starts at 63.
  //Each loop represents 15 random bits, a.k.a. 'coin flips'.
  #define RND_INNER_LOOP() \
    if( coinFlips & 1 ) break; \
    coinFlips >>= 1; \
    ret -= 0x800000
  for(;;){
    coinFlips = rand();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    //At this point, the exponent is 60, 45, 30, 15, or 0.
    //If the exponent is 0, then the number equals 0.0f.
    if( ! (ret & 0x3F800000) ) return 0.0f;
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
  }
  return *((float *)(&ret));
}
  • 8
    interesting approach, I'd like to upvote but, I really don't understand what's going on – hasen Dec 05 '09 at 03:56
2

If you know that your floating point format is IEEE 754 (almost all modern CPUs including Intel and ARM) then you can build a random floating point number from a random integer using bit-wise methods. This should only be considered if you do not have access to C++11's random or Boost.Random which are both much better.

float rand_float()
{
    // returns a random value in the range [0.0-1.0)

    // start with a bit pattern equating to 1.0
    uint32_t pattern = 0x3f800000;

    // get 23 bits of random integer
    uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());

    // replace the mantissa, resulting in a number [1.0-2.0)
    pattern |= random23;

    // convert from int to float without undefined behavior
    assert(sizeof(float) == sizeof(uint32_t));
    char buffer[sizeof(float)];
    memcpy(buffer, &pattern, sizeof(float));
    float f;
    memcpy(&f, buffer, sizeof(float));

    return f - 1.0;
}

This will give a better distribution than one using division.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 8
    I'm not sure why you're saying this would give a "better distribution". In fact, this will give *exactly the same* distribution as just `return (float)random23 / (1 << 23)`. (Yes, I just [tested this](http://ideone.com/aEH1Qa), modifying your function to take `random32` as a parameter and running it for all values from zero up to `(1 << 23)-1`. And yes, your method does indeed give exactly the same results as division by `1 << 23`.) – Ilmari Karonen Jan 03 '16 at 16:19
1

For C++, it can generate real float numbers within the range specified by dist variable

#include <random>  //If it doesnt work then use   #include <tr1/random>
#include <iostream>

using namespace std;

typedef std::tr1::ranlux64_base_01 Myeng; 
typedef std::tr1::normal_distribution<double> Mydist;

int main() { 
       Myeng eng; 
       eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
       Mydist dist(1,10); 

       dist.reset(); // discard any cached values 
       for (int i = 0; i < 10; i++)
       {
           std::cout << "a random value == " << (int)dist(eng) << std::endl; 
       }

       return (0);
}
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Marco167
  • 371
  • 3
  • 7
  • 1
    Did you just copy and paste the code from this answer? http://stackoverflow.com/a/1118739/1538531 – Derek Nov 13 '13 at 17:39
  • Actually No. I am bit surprised to see how much they look alike! But I did initialize engine-generator Jan 1,1970. – Marco167 Nov 14 '13 at 14:35
  • Fair enough. I did notice that you initialized the generator to the epoch, but darn that code is similar! – Derek Nov 14 '13 at 15:11
  • I find it a bit odd to be giving a TR1 example, can you explain in what cases someone would have to use TR1 as opposed to C++11? – Shafik Yaghmour Aug 25 '14 at 01:46
0
#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

/* single precision float offers 24bit worth of linear distance from 1.0f to 0.0f */
float getval() {
    /* rand() has min 16bit, but we need a 24bit random number. */
    uint_least32_t r = (rand() & 0xffff) + ((rand() & 0x00ff) << 16);
    /* 5.9604645E-8 is (1f - 0.99999994f), 0.99999994f is the first value less than 1f. */
    return (double)r * 5.9604645E-8;
}

int main()
{
    srand(time(NULL));
...

I couldn't post two answers, so here is the second solution. log2 random numbers, massive bias towards 0.0f but it's truly a random float 1.0f to 0.0f.

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

float getval () {
    union UNION {
        uint32_t i;
        float f;
    } r;
    /* 3 because it's 0011, the first bit is the float's sign.
     * Clearing the second bit eliminates values > 1.0f.
     */
    r.i = (rand () & 0xffff) + ((rand () & 0x3fff) << 16);
    return r.f;
}

int main ()
{
    srand (time (NULL));
...
Mike Mestnik
  • 313
  • 5
  • 14
0

rand() return a int between 0 and RAND_MAX. To get a random number between 0.0 and 1.0, first cast the int return by rand() to a float, then divide by RAND_MAX.

James Curran
  • 101,701
  • 37
  • 181
  • 258