При генерации нормально распределенных случайных значений, что является наиболее эффективным способом определения диапазона?

FYI: random == псевдослучайный

а. при генерации равномерно-случайных чисел я могу указать диапазон, т.е.:

(Math.random()-Math.random())*10+5
//generates numbers between -5 and 15

В. генерируя набор случайных значений с версией нормальной случайной случайности Гаусса:

//pass in the mean and standard deviation
function randomNorm(mean, stdev) {
  return Math.round((Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1))*stdev+mean);
}

//using the following values:
{
  mean:400, 
  standard_deviation:1
  //results in a range of 397-403, or +-range of 3
},
{
  mean:400, 
  standard_deviation:10
  //results in a range of 372-429, or +-range of 30
},
{
  mean:400, 
  standard_deviation:25
  //results in a range of 326-471, or +-range of 75
}

каждый из них дает мне диапазон приблизительно стандартного_выхода * (+ - 3) (если я оставил программу более продолжительной).

С. Я могу рассчитать этот диапазон следующим образом:

  • Предполагая, что я хочу диапазон от 300 до 500, поэтому var total_range = 200;
  • my mean is 400, my + -range - total_range/2 (var r = 100)
  • поэтому standard_deviation будет r/3 или в этом случае 33.333.

Кажется, это работает, но я понятия не имею, что я делаю с математикой, поэтому я чувствую себя идиотом, это решение кажется клочковым и не совсем точным.

Мой вопрос: есть ли какая-то формула, которую я танцую вокруг, что может помочь мне здесь? мои требования следующие:

  • должен иметь возможность точно определять диапазон чисел.
  • должно быть сделано в JavaScript, насколько это возможно.

Я думаю, может быть, я рядом, но это не совсем так.

Ответ 1

Вычитание двух случайных чисел не дает вам нормального распределения, оно даст вам числа, которые линейно убывают с обеих сторон от нуля. См. Красную диаграмму в этой скрипке:

http://jsfiddle.net/Guffa/tvt5K/

Чтобы получить хорошее приближение нормального распределения, добавьте шесть случайных чисел вместе. См. Зеленую диаграмму в скрипке.

Итак, чтобы получить нормально распределенные случайные числа, используйте:

((Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random()) - 3) / 3

Этот метод основан на центральной предельной теореме, обозначенной как второй метод здесь: http://en.wikipedia.org/wiki/Normal_distribution#Generating_values_from_normal_distribution

Ответ 2

Я хотел иметь гауссовские случайные числа между 0 и 1, а после многие тесты (спасибо @Guffa ответ тоже), я нашел это быть лучшим:

function gaussianRand() {
  var rand = 0;

  for (var i = 0; i < 6; i += 1) {
    rand += Math.random();
  }

  return rand / 6;
}

И в качестве бонуса:

function gaussianRandom(start, end) {
  return Math.floor(start + gaussianRand() * (end - start + 1));
}