2016-08-25 4 views
4

Я уже знаю, как генерировать случайные числа в диапазоне. Я могу сделать это с помощьюГенерировать случайные числа в определенном диапазоне со стандартным отклонением?

rand.nextInt((max - min) + 1) + min; 

Проблема заключается в том, что я хотел бы, чтобы установить стандартное отклонение для этих чисел. Цифры также должны быть положительными, и они не между 0 и 1

EDIT я удалил класс ThreadLocalRandom, потому что я не могу установить семя в этом классе, и эти случайные числа должны быть воспроизводимы в другой системе.

+2

Не могли бы вы помочь? ... http://stackoverflow.com/questions/31754209/can-random-nextgaussian-sample-values-from-a-distribution-with-different-mean –

+0

Подсказка: мне потребовалось меньше времени, чтобы найти "дублированный" вопрос, чем прочитать ваш вопрос. Думаю: писать ваш вопрос занял еще больше времени. Так пожалуйста; сделайте некоторые предварительные исследования в следующий раз. – GhostCat

+0

@GhostCat «дублированный» ответ не решает мою проблему, потому что мне нужны номера в диапазоне. – statboy

ответ

3

Выбор стандартного отклонения (или дисперсии) для ограниченного распределения может выполняться только с учетом ограничений, которые зависят от выбранного распределения и границ (min, max) вашего интервала. В некоторых дистрибутивах вы можете сделать дисперсию сколь угодно малой (например, Beta distribution), другие дистрибутивы (например, Uniform distribution) не допускают гибкости после того, как были установлены границы (min, max). В любом случае вы можете никогда не делать, чтобы сделать дисперсию произвольно большой - границы этого не мешают (они всегда будут вводить выражение для дисперсии распределения).

Я проиллюстрирую это на очень простой пример, который может быть реализован без каких-либо сторонних библиотек. Предположим, что вы хотите симметричное распределение на интервале (min, max), симметрию, подразумевающую, что среднее E (X) распределения расположено в середине интервала: E(X) = (min + max)/2.

Использование Рэндом nextDouble как в x = a + (b - a) * rnd.nextDouble() даст вам равномерно распределенную случайную величину в интервале a <= x < b, который имеет фиксированную дисперсию Var(X) = (b - a)^2/12 (не то, что мы хотим).

OTH, имитируя симметричную triangular distribution на том же интервале (a, b) даст нам случайную мерный ти то же среднее значение, но только половина дисперсии: Var(X) = (b - a)^2/24 (также фиксированной, так и не то, что мы хотим).

A симметричный trapezoidal distribution с параметрами (a < b < c < d) лежит где-то посередине равномерного и треугольного распределения на интервале (a, d). Условие симметрии влечет d - c = b - a, в следующем я буду ссылаться на расстояние b - a как x или как «смещение» (я составил это имя, это не технический термин).

Если вы позволите x приблизиться к 0.0 сверху, трапеция начнет выглядеть очень похожей на равномерное распределение, и ее дисперсия будет стремиться к максимально возможному значению (d - a)^2/12. Если вы дадите x приблизительное значение (d - a)/2 снизу, трапеция будет очень похожа на симметричное распределение треугольника, и ее дисперсия приблизится к минимально возможному значению (d - a)^2/24) (но обратите внимание, что нам следует немного держаться от этих экстремальных значений в чтобы не нарушить формулу дисперсии или наш алгоритм для трапеции).

Таким образом, идея заключается в том, чтобы построить распределение трапециевидного со значением для x, что дает стандартное отклонение вы хотите, учитывая условие, что ваше целевое стандартное отклонение должно лежать в открытом диапазоне (примерно), заданной (0.2041(d - a), 0.2886(d - a)). Для удобства предположим, что a = min = 2.0 и d = max = 10.0, который дает нам этот диапазон возможных stddevs: (1.6328, 2.3088).Предположим далее, что мы хотим построить распределение с stddev 2.0 (что, конечно, должно быть в допустимом диапазоне).

Решение этого требует 3 шага:

1) мы должны иметь формулу для дисперсии данного min, max и допустимого значения для смещения x

2) нам необходимо каким-то образом «инвертирует» это выражение чтобы дать нам значение x для целевой дисперсии

3), как только мы знаем значение x мы должны построить случайную переменную, которая имеет симметричное распределение трапеций с параметрами (min, max, x)

Шаг 1:

/** 
* Variance of a symmetric trapezoidal distribution with parameters 
* {@code a < b < c < d} and the length of {@code d - c = b - a} 
* (by symmetry) identified by {@code x}. 
* 
* @param a support lower bound 
* @param d support upper bound 
* @param x length of {@code d - c = b - a}, constrained to lie in the open 
*   interval {@code (0, (d-a)/2)} 
* @return variance of the symmetric trapezoidal distribution defined by 
*   the triple {@code (a, d, x)} 
*/ 
static double varSymTrapezoid(double a, double d, double x) { 
    if (a <= 0.0 || d <= 0.0 || a >= d) { 
     throw new IllegalArgumentException(); 
    } 
    if (x <= 0.0 || x >= (d - a)/2) { 
     throw new IllegalArgumentException(); 
    } 
    double b = a + x; 
    double c = d - x; 
    double b3 = pow(b, 3); 
    double c3 = pow(c, 3); 
    double ex2p1 = pow(b, 4)/4 - a * b3/3 + pow(a, 4)/12; 
    double ex2p2 = (c3/3 - b3/3) * (d - c); 
    double ex2p3 = pow(c, 4)/4 - d * c3/3 + pow(d, 4)/12; 
    double ex2 = (ex2p1 + ex2p2 + ex2p3)/((d - b) * (d - c)); 
    return ex2 - pow((a + d)/2, 2); 
} 

Обратите внимание, что эта формула справедлива только для симметричных распределений трапециевидных. В качестве примера, если вы вызовете этот метод со смещением 2,5 (varSymTrapezoid(2.0, 10.0, 2.5)), это вернет вам отклонение приблизительно 3.0416, которое слишком низкое (нам нужно 4.0), что означает, что смещение 2,5 слишком велико (более высокие перемещения дают более низкие отклонения).

Выражение дисперсии - это многочлен 4-го порядка в x, который я бы не хотел аналитически решать. Однако для целевого x в допустимом диапазоне это выражение монотонно убывает, поэтому мы можем построить функцию, которая пересекает нуль для нашей целевой дисперсии и решает эту задачу простым bisection. Это

Шаг 2:

/** 
* Find the displacement {@code x} for the given {@code stddev} by simple 
* bisection. 
* @param min support lower bound 
* @param max support upper bound 
* @param stddev the standard deviation we want 
* @return the length {@code x} of {@code d - c = b - a} that yields a 
* standard deviation roughly equal to {@code stddev} 
*/ 
static double bisect(double min, double max, double stddev) { 
    final double eps = 1e-4; 
    final double var = pow(stddev, 2); 
    int iters = 0; 
    double a = eps; 
    double b = (max - min)/2 - eps; 
    double x = eps; 
    double dx = b - a; 

    while (abs(dx) > eps && iters < 150 && eval(min, max, x, var) != 0.0) { 
     x = ((a + b)/2); 
     if ((eval(min, max, a, var) * eval(min, max, x, var)) < 0.0) { 
      b = x; 
      dx = b - a; 
     } else { 
      a = x; 
      dx = b - a; 
     } 
     iters++; 
    } 
    if (abs(eval(min, max, x, var)) > eps) { 
     throw new RuntimeException("failed to find solution"); 
    } 
    return x; 
} 

/** 
* Function whose root we want to find. 
*/ 
static double eval(double min, double max, double x, double var) { 
    return varSymTrapezoid(min, max, x) - var; 
} 

Вызов bisect метода с желаемым значением 2,0 для стандартного отклонения (bisect(2.0, 10.0, 2.0)) дает нам необходимое смещение: ~ 1.1716. Теперь, когда значение x известно, последнее, что нам нужно сделать, это построить соответствующим образом распределенная случайная величина, которая

Шаг 3:

Это хорошо известный факт теории вероятностей сумма двух независимых равномерно распределенных случайных величин X1 ~ U[a1, b1] и X2 ~ U[a2, b2] является симметричной трапецеидально распределенной случайной величиной на интервале [a1 + a2, b1 + b2] при условии, что либо a1 + b2 < a2 + b1 (случай 1), либо a2 + b1 < a1 + b2 (случай 2). Мы должны избегать случая a2 + b1 = a1 + b2 (случай 3), так как тогда сумма имеет симметричное треугольное распределение, которое мы не хотим.

Мы выберем случай 1 (a1 + b2 < a2 + b1). В этом случае длина b2 - a2 будет равна «смещению» x.

Таким образом, все, что мы должны сделать, это выбрать границах интервала a1, a2, b1 и b2, такие, что a1 + a2 = min, b1 + b2 = max, b2 - a2 = x и выше неравенство fullfilled:

/** 
* Return a pseudorandom double for the symmetric trapezoidal distribution 
* defined by the triple {@code (min, max, x)} 
* @param min support lower bound 
* @param max support upper bound 
* @param x length of {@code max - c = b - min}, constrained to lie in the 
*   open interval {@code (0, (max-min)/2)} 
*/ 
public static double symTrapezoidRandom(double min, double max, double x) { 
    final double a1 = 0.5 * min; 
    final double a2 = a1; 

    final double b1 = max - a2 - x; 
    final double b2 = a2 + x; 

    if ((a1 + b2) >= (a2 + b1)) { 
     throw new IllegalArgumentException(); 
    } 

    double u = a1 + (b1 - a1) * rnd.nextDouble(); 
    double v = a2 + (b2 - a2) * rnd.nextDouble(); 
    return u + v; 
} 

Вызов symTrapezoidRandom(2.0, 10.0, 1.1716) неоднократно дает вам которые имеют требуемое распределение.

Вы можете сделать очень похожие вещи с другими, более сложными, дистрибутивами, такими как Beta. Это даст вам другие (как правило, более гибкие) ограничения на допустимые отклонения, но для этого вам понадобится сторонняя библиотека, например commons.math.

abs, pow, sqrt в коде относится к статический импортируемым методам java.lang.Math и rnd является экземпляром java.util.Random.

+0

Не могли бы вы рассказать мне, откуда вы получили формулу дисперсии для симметричной трапеции? Я не мог найти его нигде. – apophis

+0

@apophis Я вычислил его вручную, используя ручку и бумагу. Самое смешное, что приведенная формула [здесь] (http: //doc.openturns.org/openturns-latest/sphinx/user_manual/_generated/openturns.Trapezoidal.html) ошибочен, хотя он выглядит разумным. Возможно, они только заменили переменные. [Это] (https://de.wikipedia.org/wiki/Trapezverteilung), еще хуже, что даже «E (X)» является правильным. Я не мог найти ни одного правильного уравнения, которое использует представление '(a, b, c, d)', поэтому мне пришлось самому его вывести. –

Смежные вопросы