Функция плотности вероятности с использованием стандартной библиотеки?

Будучи в состоянии использовать std <random> генерировать случайные числа различных распределений проб отлично... Теперь, есть ли способ вычислить вероятность набора чисел с учетом распределения и его параметров, используя стандартную библиотеку?

Я знаю, что могу самостоятельно кодировать функции плотности вероятности и массы для любых распределений (см. Пример ниже для единственной случайной переменной), но я бы предпочел использовать стандартную библиотеку, если бы мог.

long double exponential_pdf(long double x, long double rate) {

    if ( x < 0.0 ) {
        return 0.0;
    }
    if ( rate < 0.0 ) {
        return NOT_A_NUMBER;
    }
    auto    pdf = rate * exp( - rate * x);
    return  pdf;
}

3 ответа

Решение

Начиная с C++11, Стандартная библиотека содержит набор дистрибутивов, которые можно использовать для генерации случайных чисел. К сожалению, в стандартной библиотеке нет функций для вычисления плотностей вероятностей, кумулятивных распределений или функций квантиля.

Что касается обоснования того, почему это не было включено в Стандартную библиотеку, см. Рабочий документ N1398 (выделено мной).

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

Я не совсем согласен с этим рассуждением: хотя верно, что функции плотности достаточно легко кодировать, то же самое не относится к кумулятивным функциям распределения или квантиля.

В качестве обходного пути вы можете перейти к Boost Math Toolkit. Он использует те же имена, что и стандартная библиотека для распределений, но позволяет вычислять pdf() и многие другие свойства для этих распределений. Расширенные библиотеки часто попадают в Стандарт, а если нет, то они, по крайней мере, независимы от платформы и широко доступны. Ваш пример будет что-то вроде:

#include <iostream>
#include <boost/math/distributions/exponential.hpp>

using namespace boost::math;

int main() 
{
    auto const lambda = 1.0;
    auto d = exponential_distribution<>{lambda};
    std::cout << pdf(d, 0) << "\n"; // exp(0) = 1
    std::cout << pdf(d, 1) << "\n"; // exp(-1) = 0.367879
}

Живой пример.

Кроме того, если вы уже используете C++17, есть полезная библиотека RandLib с открытым исходным кодом. В вашем примере вы могли бы просто написать

#include “RandLib.h”

void main() {
    double lambda = 1;
    ExponentialRand X(lambda);
    X.f(0); //=1
}

@dudu

Я не знаю, какой компилятор вы используете, но имейте в виду, что компилятор Microsoft Visual C++ не поддерживает длинный тип двойного примитива. Такая поддержка заставит компилятор испускать код с плавающей запятой x87.

Другие вопросы по тегам