Creating a Random Number

Former Member
Former Member
I was wondering if there is a way to get a random number between two numbers. I see that there is a Math.rand(), but this just grabs a very random number. I am trying to get a random number to draw a bitmap at random points on the screen.

Thanks for any and all the help.

Top Replies

All Replies

  • Travis posted something like this earlier in the thread:

    var num=RAND_MIN+(rand()% (RAND_MAX-RAND_MIN));

    The lower bounds is RAND_MIN and what's added to that is rand mod the difference between RAND_MAX and RAND_MIN,

    you could use

    var range= RAND_MAN-RAND_MIN;

    to skip a calculation each time, but I wanted it to be clear.

  • As I explained in my previous comment, Travis' actual post was this:

    m + Math.rand() / (RAND_MAX / (n - m + 1) + 1);

    where:

    m = the desired lower bound

    n = the desired upper bound

    (Travis' post has a typo where the descriptions of n and m are swapped. It also doesn't explain that RAND_MAX should be converted to a float before doing the division)

    RAND_MAX is the maximum number returned by Math.rand() (in the case of Monkey C, 0x7FFFFFFF)

    Also as discussed, this solution is better, but not perfect, for the same reason that the modulo solution is imperfect.

  • using mod makes it simpler

  • using mod makes it simpler

    Agreed, but if the question is "why does my random number generator seem to be biased", then the simple mod or float division answers aren't sufficient. (Although the division answer is marginally better than the mod answer)

  • And that would be calling srand only once or maybe using a better seed, maybe Time.now(),value()?

  • And that would be calling srand only once or maybe using a better seed, maybe Time.now(),value()?

    I already agreed that srand should only be called once, yet also as previously posted, neither the mod nor the float division solutions are truly unbiased, except in the corner case where RAND_MAX is a multiple of the size of the range of numbers you want.

    (Note that here as in the C standard, RAND_MAX is the maximum number the the rand function returns, *not* the upper bound of the desired range of random numbers to generate.)

    Again I will paste the explanation of why this is the case:

    stackoverflow.com/.../11758872

    The problem is that you're doing a modulo operation. This would be no problem if RAND_MAX would be evenly divisible by your modulus, but usually that is not the case. As a very contrived example, assume RAND_MAX to be 11 and your modulus to be 3. You'll get the following possible random numbers and the following resulting remainders:

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

    As you can see, 0 and 1 are slightly more probable than 2.

  • Travis posted something like this earlier in the thread:

    var num=RAND_MIN+(rand()% (RAND_MAX-RAND_MIN));

    The lower bounds is RAND_MIN and what's added to that is rand mod the difference between RAND_MAX and RAND_MIN,

    you could use

    var range= RAND_MAN-RAND_MIN;

    I'd also avoid using RAND_MAX in your example as the name of the argument/variable which represents the upper bound for the range of random numbers you want to generate, since by convention RAND_MAX is supposed to be a constant equal to the largest number that the rand function ever returns (in the C standard and in previous examples in this thread.)

    e.g. In Travis's example, RAND_MAX = 0x7FFFFFFF, because Monkey C's Math.rand returns a Number (signed 32-bit integer).

    EDIT: Note to mods, I couldn't post this comment and the previous one as a single comment, because the forum kept giving me an error, but somehow posting as separate comments works? Very frustrating.

  • Jim - just curious why Time.now() is better? Here are the values produced by these functions.

    And calling srand each time doesn't hurt, right? If the implementation of rand() is biased, then a new seed prior to each call could actually reduce the bias?

  • I'm guessing that a different seed might help - that's all.  System getTimer restarts at zero each time a device is powered up

  • And calling srand each time doesn't hurt, right?

    Did you read the link I posted about why calling srand() multiple times is a bad idea? Suppose you use Time.Now.value() (number of seconds since the UTC epoch) as your seed and you call your random number code more than once in the same second -- you will get the same "random number" twice. Sure, you can increase the precision by using milliseconds to try to avoid that, but it's still pointless to call srand() every time.

    Short answer: calling srand() is not like "rolling the dice" for the random number generator. Nor is it like shuffling a deck of cards. If anything, it's more like just cutting a deck of cards.

    If the implementation of rand() is biased,

    It's not that rand() is biased per se, it's how you use it: the simple modulo or float division to get a number in a certain range is biased.

    To be clear, both of these simple solutions are biased:

    (The most common solution under discussion - modulo)

    min + (Math.rand() % (max - min + 1))

    (The alternative that Travis posted - float division)

    min + Math.rand() / (RAND_MAX.toFloat() / (max - min + 1) + 1);

    where:

    RAND_MAX = the largest number that Math.rand() can return (0x7FFFFFFF in Monkey C)

    min = the lowest random number you want to generate

    max = the highest random number you want to generate

    The very simple reason is that in general, you can't distribute RAND_MAX + 1 integers evenly into max - min + 1 buckets.

    https://c-faq.com/lib/randrange.html

    When N is close to RAND_MAX, and if the range of the random number generator is not a multiple of N (i.e. if (RAND_MAX+1) % N != 0), all of these methods break down: some outputs occur more often than others. (Using floating point does not help; the problem is that rand returns RAND_MAX+1 distinct values, which cannot always be evenly divvied up into N buckets.)

    https://stackoverflow.com/a/11758872

    The problem is that you're doing a modulo operation. This would be no problem if RAND_MAX would be evenly divisible by your modulus, but usually that is not the case. As a very contrived example, assume RAND_MAX to be 11 and your modulus to be 3. You'll get the following possible random numbers and the following resulting remainders:

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

    As you can see, 0 and 1 are slightly more probable than 2.

    One option to solve this is rejection sampling: By disallowing the numbers 9 and 10 above you can cause the resulting distribution to be uniform again.

    The suggested solution here is to call rand() multiple times, rejecting certain values:

    To be fair, the modulo or float division solutions are "good enough" for most people. But again, if the question is "why does my random number code seem to be biased?" the answer is that the simple solutions aren't perfect.