2

i'm getting a bit confused with operators and there use with random generation. I guess i'm just asking does this code do what I want it to?

Generate a 'random' TRUE or FALSE depending on what probability I assigned the function.

bool randtf(int probability) {
    if ((rand() % 100) < probability)
        return true;
    else
        return false;
}

so if randtf(63) it has a 63% chance of being TRUE?

Any guidance would be much appreciated. Thanks.

Elgoog
  • 2,205
  • 7
  • 36
  • 48

4 Answers4

6

Yes, to a first approximation.

No, more accurately. rand() returns a number between 0 and RAND_MAX, which in practice will always be of the form (1 << n) - 1. This isn't a multiple of 100, so you won't get a perfectly uniform distribution when you take the modulo.

You can fix that by using rejection sampling. For the sake of argument, let's assume RAND_MAX == 32767 (i.e. 16-bit). The first step is to keep generating random numbers, rejecting them until you obtain one less than 32700 (the largest multiple of 100 that's less than RAND_MAX). If you then do the modulo trick on that, you will get a uniform distribution.

Of course, this assumes a sane, statistically robust, implementation of rand(), which is quite an assumption!

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • If RAND_MAX is 32767 The bottom 0-27 will be slightly more likely than 28-99 by ~3.125% – Mooing Duck Oct 26 '11 at 23:55
  • Not with C++03 standard library. Can be done with http://www.boost.org/doc/libs/1_38_0/libs/random/random-distributions.html. Unsure about C++11, the draft had a better RNG, but I haven't verified that made it to the final. – Mooing Duck Oct 26 '11 at 23:57
  • @Elgoog see [here](http://stackoverflow.com/questions/7887941/random-number-from-9-to-9-in-c/7888357#7888357) or directly [the man page of rand](http://linux.die.net/man/3/rand) (The Notes section) – Shahbaz Oct 27 '11 at 00:06
0

MAX_RAND is not a multiple of 100, so your distribution would technically not be fair. You have to scale rand(), not mod it.

MartyTPS
  • 530
  • 2
  • 5
  • why because rand() is not very random in the first place? – MartyTPS Oct 27 '11 at 00:03
  • 1
    @OliCharlesworth, by scale I assume he means `(float)rand()/RAND_MAX < prob / 100.0`, what would be wrong with that? – mikerobi Oct 27 '11 at 00:04
  • @mikerobi: Because `rand` returns an integer. There is not a perfect n-to-1 mapping between the input domain [0,RAND_MAX] and the output domain [0,99]. (Consider a simpler case where RAND_MAX was 7, and you wanted a random number between 0 and 2, inclusive). – Oliver Charlesworth Oct 27 '11 at 00:08
  • ok, smart-*$$.... so the monster will show up a billisecond too soon on average. :) – MartyTPS Oct 27 '11 at 00:18
  • @MartyTPS: This is exactly as non-uniform as the mod version; they fail for the same reason. – Oliver Charlesworth Oct 27 '11 at 00:19
  • ok, so scale your input parameter and just use rand() as is. You get closer. – MartyTPS Oct 27 '11 at 00:34
  • @Marty: You don't. Fundamentally, you are trying to map (e.g.) 32768 things onto 100 things, and that just doesn't divide up equally. – Oliver Charlesworth Oct 27 '11 at 00:42
  • @Marty: for 32767->100 mapping, some appear over 3% more often. 3% might (or mght not) be too much for whatever it is doing. He's implied he wants better – Mooing Duck Oct 27 '11 at 01:38
  • No I just suggested a 100->32767 mapping of the input instead. – MartyTPS Oct 27 '11 at 01:40
  • Regardless of how accurately you can divide up the range we still have the problem that rand() is just a good enough for games random number. – MartyTPS Oct 27 '11 at 01:54
0

It depends on what rand() returns, and in particular if the range of possible numbers is a an exact multiple of 100 (and uniformly distributed). In general, using modulo does not necessarily give you the correct statistical behaviour.

For example's sake, suppose your rand() only returned the valued 0, 1, 2, 3, 4, 5, 6; and you said rand() % 5 < p (where 0 <= p < 5). But behold: This takes the values 0 and 1 twice, but 2, 3 and 4 only once across the range of valid source numbers! So with p = 4 you don't actually get 80% probability, but only 1/7.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

Even if the random generator is perfectly random, because rand() only generates numbers from 0 to 0x7FFF, it cannot be perfectly distributed. consider the following code:

int arr[100] = { 0 };
for( int i=0; i<0x7FFF; i++ ){
arr[ i % 100 ]++;
}

for( int i=0; i<100; i++ ){
    cout << arr[i] << endl;
}
return 0;

If you run this code, it's not going to give you the same number:

328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
328
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
327
Press any key to continue . . .
JosephH
  • 8,465
  • 4
  • 34
  • 62