1

I want to generate a number that is close to zero with a certain general range. For example, let's say I want the number to fall under 10 90% of the time, but there's a small chance that it will be 15, 20, or even 30. The higher the number, the lower the chance of receiving it.

I've tried looking for something with the keywords "weighted probability" but can't find anything that leads in the right direction.


Update:

I ended up using the Box-Muller transform (see accepted answer). Here's the simple code I wrote:

const E = 2.71828183;

function getRandomCurvedValue(temp.median, temp.density) {
  return this.getCurvedValue(random(0, 1), temp.median, temp.density);
}

function getCurvedValue(temp.value, temp.median, temp.density) {
  return temp.median + (temp.density * log(E, (temp.value / (1 - temp.value)))); 
}
Tom Marthenal
  • 3,066
  • 3
  • 32
  • 47

3 Answers3

5

I think you're looking for a normal distribution.

A normal distribution has two variables you can change: The mean and the standard deviation. The mean would be 0 in your case and the standard deviation appropriately chosen so that 90 percent of values fall below 10. (Based on the tables in the Wikipedia article, I think a standard deviation of 1.645 is appropriate.)

You can use the Box-Muller transform as an easy way of generating normal-distributed random values from uniformly-distributed ones. Also you would need to use the absolute value of the result since you only want values in the range of [0, ∞).

Community
  • 1
  • 1
Joey
  • 344,408
  • 85
  • 689
  • 683
3

If I understand you right, you need positive random numbers only. In this case you can use for example exponentially distributed random numbers. This distribution has a single parameter, lambda. If you "want the number to fall under 10 90% of the time", then lambda can be calculated as -ln(0.1) / 10 (here ln is the natural logarithm). Generally, if you want it to fall below x with probability p, then lambda = -ln(1 - p) / x (in your example, p = 0.9 and x = 10). You can easily generate exponentially distributed random numbers with a given lambda parameter with this formula: -ln(1 - rand()) / lambda, where the function rand() is function which can generate equally distributed random numbers between 0 and 1.

kol
  • 27,881
  • 12
  • 83
  • 120
0

One possibility is to generate a set of random numbers (for each iteration). The minimum of those numbers is chosen as your generated number.

Obviously, the more numbers you pick, the more likely you will have a smaller minimum number.

Example: Say you generate two random numbers in your set, 9 and 10. 9 is chosen because it is the smallest.

Say you generate four random numbers in your set, 9, 10, 11, and 8. 8 is chosen because it is your smallest.

Also with this method, it is important you have a range from which you pick the numbers, say from 1 to 100... (this is sort of a limiting factor)

varatis
  • 14,494
  • 23
  • 71
  • 114