質問

Being able to use the std <random> to generate random numbers of different prob distributions is great... Now, Is there any way to compute the probability of a set of numbers given a distribution and its parameters using the standard library?

I am aware that I can code the Probability Density & Mass Functions for whatever distributions on my own (see example below for a single random variable), but I'd rather use the standard library if I could.

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;
}
役に立ちましたか?

解決

Since C++11, the Standard Library contains a bunch of distributions that can be used for random number generation. Unfortunately, there is no functionality for computing probability densities, cumulative distributions or quantile functions in the Standard Library.

As for a rationale why this was not included in the Standard Library, see the working paper N1398 (emphasis mine)

Some libraries provide the probability density function of a given distribution as part of that distribution's interface. While this may be useful occasionally, this proposal does not provide for such a feature. One reason is separation of concerns: The distribution class templates might benefit from precomputing large tables of values depending on the distribution parameters, while the computation of the probability density function does not. Also, the function representation is often straightforward, so the user can easily code it himself.

I don't quite agree with this reasoning: while it is true that the density functions are easy enough to code, the same does not hold for the cumulative distribution or quantile functions.

As a workaround, you could go to the Boost Math Toolkit. It uses the same names as the Standard Library for the distributions, but allows you to compute pdf() and many more properties for these distributions. Boost libraries often find their way into the Standard, and if not, they are at least platform independent and widely available. Your example would be something like:

#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
}

Live Example.

他のヒント

In addition, if you are using C++17 already, there is a useful opensouce library RandLib. In your example you could just write

#include “RandLib.h”

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

@dudu

I do not know which compiler you are using, but bear in mind that Microsoft Visual C++ compiler does not support long double primitive type. Such a support will force compiler to emit x87 floating point code.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top