Генерация случайных чисел с неравномерным распределением
в JavaScript Math.random()
возвращает псевдо-случайное число с "равномерным" распределением.
мне нужно сгенерировать случайное число в диапазоне [0,1], что перекос в любую сторону. (Это означает, что больше шансов получить больше чисел рядом с 0 или рядом с 1)
В идеале я хотел бы иметь параметр для установки этой кривой.
Я предполагал, что могу сделать Math.random^2
чтобы получить такой результат, но какие более сложные способы для этого существуют?
4 ответов
Я думаю, вы хотите бета-распределения с alpha=beta=0.5
можно преобразовать равномерное случайное число в бета-распределение, используя обратное кумулятивное распределение.
unif = Math.random()
Я не знаком с javascript
, но это должно быть ясно:
beta = sin(unif*pi/2)^2
PS: вы можете генерировать много таких чисел и построить гистограмму
Edit:
для наклона к 0, преобразить beta
значения как -
beta_left = (beta < 0.5) ? 2*beta : 2*(1-beta);
для отклонения в сторону 1 преобразуйте как -
beta_right = (beta > 0.5) ? 2*beta-1 : 2*(1-beta)-1;
можно использовать окно.криптографический.getRandomValues, где имеется
<div id="result"></div>
var randVal = new Uint8Array(1);
window.crypto.getRandomValues(randVal);
document.getElementById("result").textContent = randVal[0] / 255;
On jsfiddle
(если это то, о чем вы просите, я не уверен)
или, может быть, как этот
<div id="result"></div>
function poissonRandomNumber(lambda) {
var L = Math.exp(-lambda),
k = 0,
p = 1;
do {
k = k + 1;
p = p * Math.random();
} while (p > L);
return k - 1;
}
document.getElementById("result").textContent = poissonRandomNumber(100);
на jsfiddle
Я думаю, вам нужно пересмотреть свой вопрос. Пуассон-это распределение подсчета, заданное в терминах скорости, например, сколько вхождений чего-то я вижу в среднем за период времени. Он дает положительные целые числа, поэтому результат не может быть только в диапазоне [0,1]. Не могли бы Вы уточнить, чего вы хотите?
независимо от того, для генерации Пуассона со скоростью лямбда один алгоритм:
threshold = Math.exp(-lambda)
count = 0
product = 1.0
while (product *= rand) >= threshold {
count += 1
}
return count
где "rand" - вызов функции для равномерного(0,1). Я не знаю javascript, но это должно быть достаточно просто для вас, чтобы реализовать.
отвечая на отредактированный вопрос:
существует несколько распределений, которые генерируют результаты в ограниченном диапазоне, но многие из них не для слабонервных, таких как семейство Джонсонов или бета-распределение.
легким было бы распределение треугольников. Функция sqrt(Рэнд) даст распределение треугольник, образованный к 1, а (1-корень(1-Рэнд)) даст распределение треугольников сгруппировано к нулю.
более общий треугольник с режимом (наиболее частое значение) в m (где 0
if rand <= m
return m * Sqrt(rand)
else
return 1 - ((1 - m) * Sqrt(1 - rand))
обратите внимание, что каждый вызов rand является отдельным однородным случайным числом, это будет неправильно, если вы создадите одно значение для rand и будете использовать его повсюду.
Я просто придумал более простой способ получить случайные числа, перекошенные в каждую сторону, и у которых нет никаких зависимостей.
этот метод использует два из регулярных случайных чисел Javascript. Первый умножается на себя (чем больше показатель, тем больше эффект перекоса), а второй выбирает, на какую сторону распределения перекосить.
function skewedRandom() {
const a = Math.pow(Math.random(), 2);
if (Math.random() < 0.5) {
return a;
}
return 1 - a;
}
в этом коде показатель равен 2. Пример гистограммы из 10 000 исполнений с показателем в 2 как и выше:
с показателем 3: