Функция нормального распределения - PullRequest
2 голосов
/ 18 марта 2009

редактировать

Итак, на основании полученных ответов (спасибо, что уделили время), у меня возникает ощущение, что я, вероятно, НЕ ищу функцию нормального распределения. Возможно, я попытаюсь переписать то, что я хочу сделать.

Допустим, у меня есть объект, который возвращает число от 0 до 10. И это число управляет «скоростью». Однако вместо 10, являющегося максимальной скоростью, мне нужно 5, чтобы быть максимальной скоростью, и все, что ниже или выше, будет соответственно замедляться. (с ослаблением, таким образом, кривая колокола)

Надеюсь, это понятнее; /


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

Я пытаюсь выяснить, как написать функцию в obj-C, где я определяю границы, например (0 - 10), а затем, если x = foo y =? .... где x выполняет что-то вроде 0,1,2,3,4,5,6,7,8,9,10, а y выполняет 0,1,2,3,4,5,4,3,2 , 1,0 но только по кривой

Что-то вроде прикрепленного изображения.

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

Так может кто-нибудь помочь мне здесь? И если есть несколько хороших сайтов, которые показывают полезные математические функции, я бы с удовольствием их проверил.

ТИА !!!

-добавлен
Я не ищу случайное число, я ищу .. например: если х = 0 у должно быть 0, если х = 5 у должно быть 5, если х = 10 у должно быть 0 .... и все остальные не так очевидны между числами

альтернативный текст http://dizy.cc/slider.gif

Ответы [ 8 ]

3 голосов
/ 18 марта 2009

То, что вы хотите построить - это функция плотности вероятности (pdf) нормального распределения. Вы можете найти его в могучей Википедии .

К счастью, PDF для нормального распределения не сложно реализовать - некоторые другие связанные функции значительно хуже, потому что они требуют функции ошибки.

Чтобы получить график, подобный тому, который вы показали, вам нужно среднее значение 5 и стандартное отклонение около 1,5. Медиана, очевидно, является центром, и вычислить подходящее стандартное отклонение с учетом левой и правой границ не особенно сложно.

Функция для вычисления значения y в pdf с учетом координаты x, стандартного отклонения и среднего значения может выглядеть примерно так:

double normal_pdf(double x, double mean, double std_dev) {
    return( 1.0/(sqrt(2*PI)*std_dev) *
            exp(-(x-mean)*(x-mean)/(2*std_dev*std_dev)) );
}
3 голосов
/ 18 марта 2009

Хорошо, ваши правки действительно проясняют ситуацию. Вы не ищете ничего общего с обычным распределением, просто приятная плавная функция линейного изменения. Пол , который предоставляет Пол , подойдет, но сложно изменить другие значения. Это можно сделать немного более гибким (мои примеры кода написаны на Python, который очень легко перевести на любой другой язык):

def quarticRamp(x, b=10, peak=5):
    if not 0 <= x <= b:
        raise ValueError   #or return 0
    return peak*x*x*(x-b)*(x-b)*16/(b*b*b*b)

Параметр b - это верхняя граница для области, на которой вы хотите иметь наклон (10, в вашем примере), а peak - как высоко вы хотите подняться (5, в примере).

Лично мне нравится подход квадратичного сплайна, который немного дешевле в вычислительном отношении и имеет другую кривую (эту кривую действительно удобно использовать в паре специальных приложений, которые для вас вообще не имеют значения):

def quadraticSplineRamp(x, a=0, b=10, peak=5):
    if not a <= x <= b:
        raise ValueError   #or return 0
    if x > (b+a)/2:
        x = a + b - x
    z = 2*(x-a)/b
    if z > 0.5:
        return peak * (1 - 2*(z-1)*(z-1))
    else:
        return peak * (2*z*z)

Это похоже на другую функцию, но имеет нижнюю границу a (0 в вашем примере). Логика немного сложнее, потому что это несколько оптимизированная реализация кусочной функции.

Две кривые имеют немного разные формы; Вы, вероятно, не заботитесь о том, какова точная форма, и поэтому можете выбрать любой. Существует бесконечное количество функций линейного изменения, соответствующих вашим критериям; это два простых, но они могут быть настолько барочными, насколько вы захотите.

2 голосов
/ 18 марта 2009

Нормальное распределение никогда не равно 0. Пожалуйста, убедитесь, что то, что вы хотите построить, действительно нормальное распределение.

Если вы ищете только эту форму колокола (с касательной и всем остальным) Вы можете использовать следующую формулу:

x^2*(x-10)^2 for x between 0 and 10
                0 elsewhere

(Разделите на 125, если вам нужно взглянуть на 5.)

double bell(double x) {
    if ((x < 10) && (x>0))
        return x*x*(x-10.)*(x-10.)/125.;
    else
        return 0.;
}
0 голосов
/ 19 марта 2009

у = -1 * абс (х-5) + 5

0 голосов
/ 18 марта 2009

Звучит так, будто вы хотите написать функцию, которая выдает кривую определенной формы. Что-то вроде y = f (x) для x в [0:10]. У вас есть ограничение на максимальное значение y, и общее представление о том, как вы хотите, чтобы кривая выглядела (несколько колоколообразно, y = 0 на краях диапазона x, y = 5, когда x = 5). Грубо говоря, вы бы вызывали вашу функцию итеративно с диапазоном x, с шагом, который дает вам достаточно точек, чтобы ваша кривая выглядела хорошо.

Так что вам действительно не нужны случайные числа, и это не имеет ничего общего с вероятностью, если вы этого не хотите (например, вы хотите, чтобы ваша кривая выглядела как контур нормального распределения или что-то в этом роде) .

Если у вас есть четкое представление о том, какая функция даст желаемую кривую, код будет тривиальным - функция для вычисления f (x) и цикл for для вызова нужного числа раз для желаемых значений x. Составьте пары x, y, и все готово. Так вот ваш алгоритм - вызовите функцию в цикле for.

Содержание подпрограммы, реализующей функцию, будет зависеть от того, как вы хотите, чтобы кривая выглядела. Если вам нужна помощь по функциям, которые могут возвращать кривую, напоминающую ваш образец, я бы направил вас к материалу для чтения в других ответах. :) Тем не менее, я подозреваю, что это на самом деле какое-то задание, и что вам уже дали функцию. Если вы действительно делаете это самостоятельно, чтобы учиться, то я снова повторяю другие предложения по чтению.

0 голосов
/ 18 марта 2009

Если вы хотите получить значение функции плотности вероятности p (x) нормального (гауссовского) распределения среднего значения mu и сигмы стандартного отклонения в точке x, формула будет иметь вид

p(x) = exp( ((x-mu)^2)/(2*sigma^2) ) / (sigma * 2 * sqrt(pi))

где pi - площадь круга, разделенная на квадрат его радиуса (приблизительно 3,14159 ...). Используя стандартную библиотеку C math.h, это:

#include <math>

double normal_pdf(double x, double mu, double sigma) {
  double n = sigma * 2 * sqrt(M_PI); //normalization factor
  p = exp( -pow(x-mu, 2) / (2 * pow(sigma, 2)) ); // unnormalized pdf

  return p / n;
}

Конечно, вы можете сделать то же самое в Objective-C.

Для справки см. Статьи Wikipedia или MathWorld .

0 голосов
/ 18 марта 2009

Попробуйте имитировать броски костей, генерируя случайные числа от 1 до 6. Если вы сложите броски из 5 независимых бросков костей, вы получите удивительно хорошее приближение к нормальному распределению. Вы можете бросить больше кубиков, если хотите, и вы получите лучшее приближение.

Вот статья , в которой объясняется, почему это работает. Возможно, это более математическая деталь, чем вы хотите, но вы можете показать ее кому-нибудь, чтобы оправдать ваш подход.

0 голосов
/ 18 марта 2009

Ну, есть старая добрая Википедия, конечно. И Mathworld .

Вам нужен генератор случайных чисел для "генерации нормально распределенных случайных отклонений" . Поскольку Objective C может вызывать обычные библиотеки C, вам нужна либо библиотека, вызываемая на C, например, GNU Scientific Library , либо для этого вы можете написать ее самостоятельно, следуя описанию здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...