| Home | Libraries | People | FAQ | More

#### Discrete Quantile Policies

If a statistical distribution is discrete then the random variable can only have integer values - this leaves us with a problem when calculating quantiles - we can either ignore the discreteness of the distribution and return a real value, or we can round to an integer. As it happens, computing integer values can be substantially faster than calculating a real value, so there are definite advantages to returning an integer, but we do then need to decide how best to round the result. The `discrete_quantile` policy defines how discrete quantiles work, and how integer results are rounded:

    enum discrete_quantile_policy_type
    {
       real,
       integer_round_outwards, // default
       integer_round_inwards,
       integer_round_down,
       integer_round_up,
       integer_round_nearest
    };

    template <discrete_quantile_policy_type>
    struct discrete_quantile;

The values that `discrete_quantile` can take have the following meanings:

###### real

Ignores the discreteness of the distribution, and returns a real-valued result. For example:

    #include <boost/math/distributions/negative_binomial.hpp>

    using namespace boost::math;
    using namespace boost::math::policies;

    typedef negative_binomial_distribution<
          double,
          policy<discrete_quantile<integer_round_inwards> >
       > dist_type;

    // Lower quantile:
    double x = quantile(dist_type(20, 0.3), 0.05);
    // Upper quantile:
    double y = quantile(complement(dist_type(20, 0.3), 0.05));

Results in `x = 27.3898` and `y = 68.1584`.

###### integer_round_outwards

This is the default policy: an integer value is returned so that:

- Lower quantiles (where the probability is less than 0.5) are rounded down.
- Upper quantiles (where the probability is greater than 0.5) are rounded up.

This is normally the safest rounding policy, since it ensures that both one and two sided intervals are guaranteed to have at least the requested coverage. For example:

    #include <boost/math/distributions/negative_binomial.hpp>

    using namespace boost::math;

    // Lower quantile rounded down:
    double x = quantile(negative_binomial(20, 0.3), 0.05);
    // Upper quantile rounded up:
    double y = quantile(complement(negative_binomial(20, 0.3), 0.05));

Results in `x = 27` (rounded down from 27.3898) and `y = 69` (rounded up from 68.1584).

The variables x and y are now defined so that:

    cdf(negative_binomial(20), x) <= 0.05
    cdf(negative_binomial(20), y) >= 0.95

In other words we guarantee at least 90% coverage in the central region overall, and also no more than 5% coverage in each tail.

###### integer_round_inwards

This is the opposite of integer_round_outwards: an integer value is returned so that:

- Lower quantiles (where the probability is less than 0.5) are rounded up.
- Upper quantiles (where the probability is greater than 0.5) are rounded down.

For example:

    #include <boost/math/distributions/negative_binomial.hpp>

    using namespace boost::math;
    using namespace boost::math::policies;

    typedef negative_binomial_distribution<
          double,
          policy<discrete_quantile<integer_round_inwards> >
       > dist_type;

    // Lower quantile rounded up:
    double x = quantile(dist_type(20, 0.3), 0.05);
    // Upper quantile rounded down:
    double y = quantile(complement(dist_type(20, 0.3), 0.05));

Results in `x = 28` (rounded up from 27.3898) and `y = 68` (rounded down from 68.1584).

The variables x and y are now defined so that:

    cdf(negative_binomial(20), x) >= 0.05
    cdf(negative_binomial(20), y) <= 0.95

In other words we guarantee at no more than 90% coverage in the central region overall, and also at least 5% coverage in each tail.

###### integer_round_down

Always rounds down to an integer value, no matter whether it's an upper or a lower quantile.

###### integer_round_up

Always rounds up to an integer value, no matter whether it's an upper or a lower quantile.

###### integer_round_nearest

Always rounds to the nearest integer value, no matter whether it's an upper or a lower quantile. This will produce the requested coverage in the average case, but for any specific example may results in either significantly more or less coverage than the requested amount. For example:

For example:

    #include <boost/math/distributions/negative_binomial.hpp>

    using namespace boost::math;
    using namespace boost::math::policies;

    typedef negative_binomial_distribution<
          double,
          policy<discrete_quantile<integer_round_nearest> >
       > dist_type;

    // Lower quantile rounded up:
    double x = quantile(dist_type(20, 0.3), 0.05);
    // Upper quantile rounded down:
    double y = quantile(complement(dist_type(20, 0.3), 0.05));

Results in `x = 27` (rounded from 27.3898) and `y = 68` (rounded from 68.1584).