4

I wonder what is the best way to generate a random floating number between min and max. Both min and max are EXCLUSIVE.

For example, min = -1, max = 100. Then the random number can be -0.999 or 99.999, but cannot be -1 or 100.

The way I come up is first generate a random number between -1 (inclusive) and 100 (exclusive):

Math.random()*(max-min)+min

And if the value is equal to -1, get another random number until it's not -1.

The whole thing would be:

var min = -1, max = 100;
var rand = min;
while(rand==min)
    rand = Math.random()*(max-min)+min;

Is there an even better way to do this so I don't have to possibly run Math.random() several times?

Shawn
  • 2,675
  • 3
  • 25
  • 48

2 Answers2

3

You could check the random number first and use only values not equal of zero.

var min = -1,
    max = 100,
    r;

while (!(r = Math.random()));        // generate and check and use only r !== 0 values
console.log(r * (max - min) + min);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • How is this answer better than the one I provide? They are pretty much the same. I want to avoid the possibility to run `Math.random()` multiple times. Thanks! – Shawn Nov 15 '16 at 19:06
  • 1
    @Shawn It's only better in that it makes fewer calculations in the worst case that it takes several tries to get a number that isn't `min`. It's not much of an improvement because the answer to your question is "no, there is no way to generate an exclusive floating-point random number in one run of "Math.random". – 4castle Nov 15 '16 at 19:09
  • This is just bad practice. This could _in theory_ create an endless loop. – Nick Nov 15 '16 at 19:22
  • 1
    I think in theory the probability of the endless loop for this case is just 0. – Shawn Nov 15 '16 at 19:32
  • @N1ckles It's not a bad practice to have a loop that iterates infinitely with probability 0 (in other words does not loop infinitely). Even `while(Math.random() < 0.9999);` is a perfectly fine loop that is guaranteed to terminate with probability 1. In this case, the probability of it iterating even twice is so slim there is nothing to be concerned about. – Paul Nov 15 '16 at 19:35
1

Just use your code removing the limits with the desired precission

var p = 0.000001; //desired precission
var min = -1+p, max = 100-p;
rand = Math.floor(Math.random()*(max-min)+min)
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • Sorry it's just an example. It should be any floating point between -1 and 100. So it could be 0.999999. – Shawn Nov 15 '16 at 19:12
  • 1
    In this case replace p value with javascript max precission for double values. I think there is no other way to avoid several calls to Math.random – pedrofb Nov 15 '16 at 19:17
  • Is 0.00000000000000001 the largest precision? – Shawn Nov 15 '16 at 19:32
  • The smallest is `5x10^-324`, which is 323 zeroes after the decimal point followed by a 5 – Paul Nov 15 '16 at 19:41
  • So set p to 5*Math.pow(10,-324) would make this a right answer? – Shawn Nov 15 '16 at 19:49
  • @Shawn Not quiet. The distance between a number and the next closest number changes depending on the number (there are as many floating point numbers between 0 and 1 as there are between 1 and Infinity), so it is a bit complicated. It's the right idea, but `p` needs to be calculated dynamically and separately for min and max. – Paul Nov 15 '16 at 19:53
  • @Shawn In the end it wouldn't make much sense to do anything other than the OP's original solution because calculating the correct value for `p` would add overhead that would be worse that the extremely rare case of calling `Math.random()` an extra time. – Paul Nov 15 '16 at 19:53
  • Yah I know there are infinite floating point numbers, but in reality it's not possible to get the next closest value. Since in Javascript the next closest value to `min` would be `min+5*Math.pow(10,-324)`, wouldn't setting `p = 5*Math.pow(10,-324)` do just the same as my original solution? – Shawn Nov 15 '16 at 20:01
  • @Shawn There aren't infinitely many. There is a finite set of representable values, and the next closest value isn't always `min + 5*Math.pow(10,-324)`. It would only be that if `min` was `0` or `-5*Math.pow(10,-324)`. The spacing between the representable numbers changes depending on the number. There are twice as many floating point numbers between 0 and 1 as there are between 1 and 2, and there are less between 5 and Infinity than there are between 1 and 2. – Paul Nov 15 '16 at 20:07
  • You could use `Number.MIN_VALUE` http://www.w3schools.com/jsref/jsref_min_value.asp, but javascript arithmetic can be weird with many decimals applied to min and Max http://stackoverflow.com/questions/11695618/dealing-with-float-precision-in-javascript So maybe is better to set a fixed number – pedrofb Nov 15 '16 at 20:11
  • @Paulpro You are not talking about math theory but how Javascript works, right? Just want to make sure. Otherwise what you are saying wouldn't make sense. – Shawn Nov 15 '16 at 20:12
  • @Shawn Yeah, how IEEE 64-bit floating point numbers work (which is what JavaScript uses). – Paul Nov 15 '16 at 20:14
  • @Shawn Still, you won't beat your original method. It is called rejection sampling and is often used when the probability of a rejection is much greater, even larger than 50%. It's not really a problem even if there are several thousand rejections before a valid value is found. In your case the probability of rejection is so low it will essentially never happen even once, and I suspect that the average amount of energy you would need to spend repeating that code enough times to get three rejections in a row is more energy than there is in the sun ( assuming a truly random Math.random() ). – Paul Nov 15 '16 at 20:20