При генерации нормально распределенных случайных значений, что является наиболее эффективным способом определения диапазона?
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));
}