1

I am trying to generate a random number that range from Number.MIN_VALUE to Number.MAX_VALUE, but the following algorithm fails due to buffer overflows (I guess) :

var randFloat = Math.floor(Math.random() * (Number.MAX_VALUE - Number.MIN_VALUE)) + Number.MIN_VALUE

Is there any way to do it ?

Magix
  • 4,989
  • 7
  • 26
  • 50
  • `crypto.getRandomValues(new Uint32Array(1))[0]` is about as good as it gets; use division to float it – dandavis Mar 28 '17 at 21:00
  • What do you mean by "use division to float it" ? – Magix Mar 28 '17 at 21:05
  • He means that the function will return a sequence of digits in the form of a whole number. Move the decimal to the left by dividing by a power of 10 to create a floating point number with the desired number of digits to the right of the decimal point. – mba12 Mar 28 '17 at 21:11
  • Generate random 64 bits, then use the formula on the https://en.wikipedia.org/wiki/Double-precision_floating-point_format to convert those bits to a number. If you don't want `Inf`s and `NaN`s retry unless the exponent equals to `7ff`. – zerkms Mar 28 '17 at 21:12
  • Won't doing this stop the random numbers from being uniform or reduce the random space ?? :/ – Magix Mar 28 '17 at 21:12
  • What exactly do you mean by uniform? – David Eisenstat Mar 28 '17 at 21:16
  • all numbers from Number.MIN_VALUE to Number.MAX_VALUE (included) have the same chance of being chosen, every time – Magix Mar 28 '17 at 21:17
  • Do you know that `MIN_VALUE` is the smallest *positive* number? – Bergi Mar 28 '17 at 21:22
  • Do you only want to generate integers? – Bergi Mar 28 '17 at 21:23
  • What exactly do you mean by "all numbers"? All real numbers? All integer numbers? All representable floating point numbers? – Bergi Mar 28 '17 at 21:24
  • All floating point numbers – Magix Mar 28 '17 at 21:25
  • Then use @zerkms' approach of generating 64 random bits (or 63 if you only want positive values) – Bergi Mar 28 '17 at 21:27

1 Answers1

1

What you could do:

function IEEEToDouble(f)
{
    return new Float64Array(f.buffer)[0];
}

var array = new Uint32Array(2); // here we allocate a 2 element unsigned 32 bit ints
window.crypto.getRandomValues(array); // here we generate 64 bits of random values
var f = IEEEToDouble(array); // and convert 64 bits to a double precision number

This generates a uniformly distributed double precision IEEE754 number. So every possible value in the whole space is equally possible to get with this code, including NaNs (it's quite a lot of NaNs there actually - 2^53 - 2) and Infinitys.

References:

Community
  • 1
  • 1
zerkms
  • 249,484
  • 69
  • 436
  • 539
  • Any way it can be done without window.crypto ? I am using Node.JS and it is not available :/ – Magix Mar 28 '17 at 21:24
  • @Magix https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback Any random source that qualifies your needs is fine. – zerkms Mar 28 '17 at 21:25
  • 2
    Depends on the definition of "uniform" - every value is equally likely, but their density is skewed heavily towards zero. – Oliver Charlesworth Mar 28 '17 at 22:05
  • I really wonder why you don't simply take `f.buffer`, instead of creating another buffer and two arrays only to copy the value from the input array. – Bergi Mar 28 '17 at 22:14
  • (see my answer to the linked question) – Bergi Mar 28 '17 at 22:29
  • 1
    @Bergi no particular reason, I just did not bother checking through the details of implementation. Now improved. – zerkms Mar 28 '17 at 22:30