4

Trying to create the following function in C:

bool randBool(double bias)

which returns either 0 or 1 randomly.

The part that is tripping me up is that I would like to allow for the user to input a "bias" in the range [-1.0, 1.0], which represents the likelihood that the output will be 0 or 1.

Here are a few examples of how the inputted bias should influence the function:

=======================================================

randBool(-1.0) should return 0 100% of the time.

randBool(1.0) should return 1 100% of the time.

randBool(-0.5) is 50% more likely to return 0 than 1.

randBool(0.05) is 5% more likely to return 1 than 0.

randBool(0.0) is no more likely to return 0 than 1.

=======================================================

I am almost certain that this is a probability problem, but I am not so familiar with the topic, so I am stumped on how to implement this function.

Oh Fiveight
  • 299
  • 1
  • 9
  • @mch: That needlessly uses a floating-point function on integers, maps `RAND_MAX` to zero (because the divisor is `RAND_MAX` instead of `RAND_MAX+1`), does not scale the result of `fmod` to -1 to 1 (or conversely, scale the bias to match the result of `fmod`). – Eric Postpischil Sep 24 '18 at 13:11
  • 2
    To be clear, when you say 0 is 50% more likely do you mean P(0) = 75% and P(1) = 25%, i.e. an absolute difference of 50% in the probabilities but you'd get three times as many zeroes as ones, or P(0) = 60% and P(1) = 40%, where P(0) is 150% P(1), i.e. a relative difference of 50%, so you'd get 50% more zeroes than ones? (I'm guessing the first, since that's consistent with your 'should return 0/1 100% of the time' examples.) – Rup Sep 24 '18 at 13:20

1 Answers1

5

Something like this :

bool randBool(double bias) {
    return rand() < ((RAND_MAX + 1.0) * ((bias + 1) / 2));
}

The ((bias + 1) / 2) part is to get the bias in the [0,1] range instead of [-1,1]. That could be avoided if the bias parameter is changed to already be in the [0,1] range.

The bias is then defined as the probability of a 1 being returned. With :

  • 0.0 (corresponds to your bias -1.0) : all zeroes
  • 0.25 (corresponds to your bias -0.5) : 25% ones, 75% zeroes
  • 0.5 (corresponds to your bias 0.0) : even mix of ones and zeroes
  • 0.525 (corresponds to your bias 0.05) : 52.5% ones, 47.5% zeroes
  • 1.0 (corresponds to your bias 1.0) : all ones


NOTES on RAND_MAX

  • If RAND_MAX < INT_MAX, then RAND_MAX + 1 can be used instead of RAND_MAX + 1.0.

  • If RAND_MAX + 1.0 cannot be represented by a double without rounding (ref. Are all integer values perfectly represented as doubles?), then the presented solution is not reliable.
    An approach on such platforms, could be to re-scale the result of rand() to a range that can be represented by either an int or a double (depending on whether you use RAND_MAX + 1 or RAND_MAX + 1.0).
    Or alternatively, use a different random number generator (that doesn't have this issue), which is probably a good idea anyway, given the many low quality implementations of rand() out there.

Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40
  • Thank you! This is exactly what I needed. I also realized that a [0,1] range works better for the inputs I will be using anyways. – Oh Fiveight Sep 24 '18 at 13:53
  • 1
    Maybe `RAND_MAX + 1.0`? Unless, of course, there's a guarantee that `RAND_MAX < INT_MAX`. – pmg Sep 24 '18 at 13:59
  • 1
    @pmg: Of course, there is also no guarantee that `RAND_MAX` is less than the point where the result of adding 1 to a `double` produces 1 more than the `double` rather than returning the same `double` due to rounding. In a C implementation with 64-bit `int` and the common IEEE-754 64-bit `double`, `RAND_MAX` could exceed 2^53, after which integer values in `double` are subject to rounding. – Eric Postpischil Sep 24 '18 at 20:33
  • @EricPostpischil : I've added some notes to my answer to cover this. Thanks for pointing it out ! – Sander De Dycker Sep 25 '18 at 07:05