Будучи в состоянии использовать 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;
}
Начиная с 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, есть полезная библиотека opensouce RandLib. В вашем примере вы могли бы просто написать
#include “RandLib.h”
void main() {
double lambda = 1;
ExponentialRand X(lambda);
X.f(0); //=1
}
@dudu
Я не знаю, какой компилятор вы используете, но имейте в виду, что компилятор Microsoft Visual C ++ не поддерживает длинный тип двойного примитива.
Такая поддержка заставит компилятор испускать код с плавающей запятой x87.