Различная вероятность для диапазонов случайных чисел - PullRequest
4 голосов
/ 17 мая 2011

Я ищу лучший способ реализации генератора случайных чисел, который позволил бы мне контролировать вероятность того, из какого диапазона будет возвращено сгенерированное число.Чтобы визуализировать то, чего я пытаюсь достичь, у меня есть картинка:

not uniform random distribution

Итак, подведем итог: допустим, мой диапазон составляет 400. В начале я хотел бы получить5% вероятность получения номера 0-20.Но в какой-то момент я бы хотел, чтобы эта вероятность увеличилась до 50%.Надеюсь, вы поняли идею.

Ответы [ 2 ]

3 голосов
/ 17 мая 2011

Хм, работая над вашим оригиналом, у меня был довольно простой алгоритм, чтобы генерировать диапазоны в массиве в соответствующей пропорции, затем случайным образом выбирать диапазон и генерировать случайное число в этом диапазоне.Без сомнения, он может быть оптимизирован при необходимости, но он работает для меня.

Выглядит как много кода, но 3/4 из них - это комментарии, тестовые данные и функции, фактические randomRange *Функция 1004 * состоит всего из 17 строк кода.

<script type="text/javascript">

function randomRange(dataArray) {

  // Helper function
  function getRandomInRange(s, f) {
    return (Math.random() * (f-s+1) | 0) + s
  }

  // Generate new data array based on probability
  var i, j = dataArray.length;
  var oArray = [];
  var o;
  while (j--) {
    o = dataArray[j];

    // Make sure probability is an integer
    for (i=0, iLen=o.probability|0; i<iLen; i++) {  
      oArray.push([o.rangeStart, o.rangeEnd]);
    }
  }

  // Randomly select a range from new data array and
  // generate a random number in that range
  var oEnd = oArray.length;
  var range = oArray[getRandomInRange(0, oArray.length - 1)]; 
  return getRandomInRange(range[0], range[1]);
}

// Test data set. Probability just has to be
// representative, so 50/50 === 1/1
var dataArray = [
  {
    rangeStart: 0, 
    rangeEnd  : 20,
    probability: 1
  },
  {
    rangeStart: 21, 
    rangeEnd  : 400,
    probability: 1
  }
];

// Test function to show range and number is randomly
// selected for given probability
function testIt() {
  var el0 = document.getElementById('div0');
  var el1 = document.getElementById('div1');
  function run() {
    var n = randomRange(dataArray);
    if (n <= 20) {
      el0.innerHTML += '*';
    } else {
      el1.innerHTML += '*';
    }
  }
  setInterval(run, 500);
}


</script>

<button onclick="testIt();">Generate random number</button>

<div>Numbers 0 - 20</div>
<div id="div0"></div>
<div>Numbers 21 - 400</div>
<div id="div1"></div>
3 голосов
/ 17 мая 2011

Мне кажется, что то, что вы ищете, это способ генерации чисел в нормальном (или гауссовском) распределении (посмотрите на страницу Википедии , если вы не знаете, что это средства).

Преобразование Бокса-Мюллера можно использовать для генерации пар нормально распределенных чисел.

Вот реализация на языке c ++ полярной формы преобразования Бокса-Мюллера, которую нетрудно перевести на javascript.

// Return a real number from a normal (Gaussian) distribution with given
// mean and standard deviation by polar form of Box-Muller transformation
double x, y, r;
do
{
    x = 2.0 * rand() - 1.0;
    y = 2.0 * rand() - 1.0;
    r = x * x + y * y;
}
while ( r >= 1.0 || r == 0.0 );
double s = sqrt( -2.0 * log(r) / r );
return mean + x * s * stddev;

Где среднее значение - среднее значение нормального распределения, а стандартное отклонение - стандартное отклонение распределения. Этот код взят из класса MersesenneTwister C ++, который я недавно использовал, и вы можете найти на странице Рика Вагнера . Вы можете найти более полезную информацию о преобразовании Бокса-Мюллера на этой странице .

...