0

I recently discovered something that bugs me...

I use RANMAR algorithm to generate random number. It is said that it is the best algorithm currently available (if you know a better one, please let me know).

I was really surprised to notice that the smallest double it can generate is roughly 1e-8.

So I tried with std::rand() with the common

(double)rand() / RAND_MAX;

way of generating double and I noticed that the smallest number is roughly 1e-9. I kind of understand that in this case because 1.0/RAND_MAX is roughly 1.0/2^31 ~ 1e-9 (on my computer, I know that RAND_MAX can have different values).

I was therefore wondering if it was possible to generate random double between [0:1] with the smallest possible value beeing near machine precision.

[edit]

I just want to be more precise... when I said that the smallest number that was generated was of the order of 1e-9, I should also have said that the next one is 0. Therefore there is a huge gap (infinity number of numbers) between 1e-9 and 0 that will be considered as 0. I mean by that if you do the following test

double x(/*is a value computed somehow in your code that is small ~1e-12*/);
if(x>rand()){ /*will be true for all random number generated that are below 1e-9*/}

So the condition will be true for too many numbers...

[/edit]

PinkFloyd
  • 2,103
  • 4
  • 28
  • 47
  • 2
    C or C++? `std::rand()` is C++. – T.C. Sep 09 '14 at 17:25
  • Generate 64 bit integers instead of 32 bit integers, perhaps? – Cornstalks Sep 09 '14 at 17:25
  • @T.C.I use C++, but why would the C case be different ? – PinkFloyd Sep 09 '14 at 17:27
  • 1
    To generate *all* possible random floating-point numbers in `[0, 1)`, with the right probability, takes order of 64 random bits, and the algorithm is rather more subtle than just "`(double)rand() / RAND_MAX`". Assuming you have a good integer RNG, the algorithm is described here: http://allendowney.com/research/rand/ I would recommend the use of a *cryptographically secure* RNG even if you don't think you need one -- use [Salsa20](https://en.wikipedia.org/wiki/Salsa20) keystream, for instance; this is performance-competitive with more conventional RNGs. – zwol Sep 09 '14 at 17:28
  • @Cornstalks I use a 64-bits processor but how do I control the value of `RAND_MAX` ? – PinkFloyd Sep 09 '14 at 17:28
  • If `RAND_MAX` is not big enough, then you need to use something other than `rand()`. It's baked into the implementation and cannot be changed. – zwol Sep 09 '14 at 17:29
  • @PinkFloyd: You don't. You can OR two random 32-bit numbers together (i.e. `uint64_t random64 = (random1 << 32) | (random2)`). Or you can use another PRNG that works with 64-bits by default. – Cornstalks Sep 09 '14 at 17:30
  • 2
    `rand()` is a pretty bad RNG. If you are using C++, check out C++11 ``. – T.C. Sep 09 '14 at 17:52
  • 2
    A [video](http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful) explains the reason why `rand()` is a bad RNG. It refers to [this question](http://stackoverflow.com/questions/4195958/how-do-i-scale-down-numbers-from-rand). Would it be good to use [uniform_real_distribution](http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution) of C++11 ? – francis Sep 09 '14 at 18:54
  • 2
    C++11's `uniform_real_distribution` together with `std::mt19937` (as shown on the page you linked to) *should* work significantly better than `rand()`. – zwol Sep 09 '14 at 19:23
  • @francis very nice video – PinkFloyd Sep 10 '14 at 07:49
  • No idea about the smallest value, but "RANMAR" usually refers to the version that generates single precision **floats**; if you want double precision, see "The 64-bit universal rng" (and beware of a typo in the initialization routine: "y = 8888 * x...") – loreb Sep 11 '14 at 16:50

0 Answers0