Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smart algorithm to randomize a Double in range but with odds

I use the following function to generate a random double in a specific range :

nextDouble(1.50, 7.00)

However, I've been trying to come up with an algorithm to make the randomization have higher probability to generate a double that is close to the 1.50 than it is to 7.00. Yet I don't even know where it starts. Anything come to mind ?

Java is also welcome.

like image 836
Yurowitz Avatar asked May 14 '26 14:05

Yurowitz


2 Answers

You should start by discovering what probability distribution you need. Based on your requirements, and assuming that random number generations are independent, perhaps Poisson distribution is what you are looking for:

a call center receives an average of 180 calls per hour, 24 hours a day. The calls are independent; receiving one does not change the probability of when the next one will arrive. The number of calls received during any minute has a Poisson probability distribution with mean 3: the most likely numbers are 2 and 3 but 1 and 4 are also likely and there is a small probability of it being as low as zero and a very small probability it could be 10.

The usual probability distributions are already implemented in libraries e.g. org.apache.commons.math3.distribution.PoissonDistribution in Apache Commons Math3.

like image 195
Karol Dowbecki Avatar answered May 16 '26 04:05

Karol Dowbecki


I suggest to not think about this problem in terms of generating a random number with irregular probability. Instead, think about generating a random number normally in a some range, but then map this range into another one in non-linear way.

Let's split our algorithm into 3 steps:

  1. Generate a random number in [0, 1) range linearly (so using a standard random generator).
  2. Map it into another [0, 1) range in non-linear way.
  3. Map the resulting [0, 1) into [1.5, 7) linearly.

Steps 1. and 3. are easy, the core of our algorithm is 2. We need a way to map [0, 1) into another [0, 1), but non-linearly, so e.g. 0.7 does not have to produce 0.7. Classic math helps here, we just need to look at visual representations of algebraic functions.

In your case you expect that while the input number increases from 0 to 1, the result first grows very slowly (to stay near 1.5 for a longer time), but then it speeds up. This is exactly how e.g. y = x ^ 2 function looks like. Your resulting code could be something like:

fun generateDouble(): Double {
    val step1 = Random.nextDouble()
    val step2 = step1.pow(2.0)
    val step3 = step2 * 5.5 + 1.5
    return step3
}

or just:

fun generateDouble() = Random.nextDouble().pow(2.0) * 5.5 + 1.5

By changing the exponent to bigger numbers, the curve will be more aggressive, so it will favor 1.5 more. By making the exponent closer to 1 (e.g. 1.4), the result will be more close to linear, but still it will favor 1.5. Making the exponent smaller than 1 will start to favor 7.

You can also look at other algebraic functions with this shape, e.g. y = 2 ^ x - 1.

like image 32
broot Avatar answered May 16 '26 03:05

broot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!