1

I've got two questions about generating numbers/single characters with given distributions.

  1. How can I implement Laplace distribution in C++? I know it's available in boost library, but let's say i can't use it. Also, i don't see it in the standard library of c+11.
  2. If i have to generate text of characters with normal distribution, will casting generated double number to int and then to char type do the trick?

    std::default_random_engine generator;
    std::normal_distribution<double> distribution(112.0,5.0);
    int number = (int)distribution(generator);
    // a-z characters
    if(number >= 97 && number  <= 122) return (char)number;
    else generate once again;
    

Hope for your help.

peter Schiza
  • 387
  • 7
  • 23
  • Why not create a normal distribution from `'A'` to `'Z'` (or their lower-case equivalents)? Note that it only works for e.g. ASCII or other encodings where the letters are encoded contiguously. – Some programmer dude Oct 26 '16 at 09:42
  • have you tried that there? what is your problem with that solution? – Hayt Oct 26 '16 at 09:45
  • If you can't use the solution from Boost.org, why do you think you can use a solution from StackOverflow.com? The licenses aren't that different. – MSalters Oct 26 '16 at 09:59

2 Answers2

1

1) Laplace distribution has explicit density (see here), which is a function from $\mathbf{R}$ to $[0,1]$, with parameters, that you can therefore implement in c++ as a member function of a class whose member variables would for instance include the distribution's parameters. Something as :

class LaplaceRandomVariable
{
    double _b;
    double _mu;
    public:
        LaplaceRandomVariable(double b, double mu)
        {
            _b = b;
            _mu = mu;
        }
        double Distribution(double x) const
        {
            return (0.5 / _b) * exp(-abs(x - _mu) / _b); //you'll need error checking for _b could be zero
        }

};

to give you a picture.

2) As for the normal distribution, normal random variables have values in $\mathbf{R}$, and so do their distribution. Instead of casting doubles to int's, were I you, I would rather use a discrete approximation of the normal random variable with given mean and variance, by binary random variables. (See for instance this.) Roughly speaking, you'd like to see a normal distribution, would your number of chars tend to infinity. That's exactly what the aforementioned binomial approximation is made for.

More precisely: consider the $B(n,p)$ distribution (wikipedia notations for us to have a common ground). When n converges to $+\infty$, $B(n,p)$ tends to approximate the normal distribution $N(np,np(1-p))$. You, you are given the mean m and the variance v of the normal distribution your chars have to been distributed as. So m=np and and v =np(1-p). As B(n,p) is with values in the set {0,...,n} and your chars span {97,...,122} = {0,...,25}+97 (+ indicating a translation), you will take n = 25. This induces p = m/25 and v = m*(1-m/25). So you are going to simulate B(m/25,m*(1-m/25)) with values in {0,...,25}, and to each generated int in {0,...,25} you will add 97, and you will static_cast<char> this int to get the corresponding char.

At this point what remains is to simulate B(n,p) with previously founded values for n and p. And for this, feel free to use :

http://www.cplusplus.com/reference/random/binomial_distribution/

Olórin
  • 3,367
  • 2
  • 22
  • 42
  • Thanks for your reply. 2. i will use binomial distribution then. It's also implemented in standard library so will be even easier. 1. And how can i use it with `std::default_random_engine generator`? Or some other function so that i could generate random characters similar to this `distribution(generator);` ? Also i want to use it to generate characters in the given range. I guess the only way is casting to int then to char type? – peter Schiza Oct 26 '16 at 13:06
  • I will edit my answer to make it include answers to your comment's question – Olórin Oct 26 '16 at 19:46
  • Thanks once again. However i meant your answer for my 1st question : P. How can i generate characters/integers with Laplace distribution using that LaplaceRandomVariable class given by you. I would like to achieve something similar to `distribution(generator);` provided by standard library. Is it possible? – peter Schiza Oct 26 '16 at 23:06
  • Well, you have in `` generators for the uniform distribution with values in [0,1], don't you ? And you have the explicite formula of the inverse cumulative distribution function F in https://en.wikipedia.org/wiki/Laplace_distribution, so you know by elementary probabilities theory how to simulate any laplace distribution, don't you ? – Olórin Oct 27 '16 at 14:29
  • Does my previous comment make sense to you ? – Olórin Oct 28 '16 at 09:24
  • More or less, yes. : P I;ve implemented function according to wikipedia article. However those are real numbers (`double` type). Is casting to `int` then to `char` a good way to get characters? Or should i change my approach? Also let's say i want to generate characters in the range `A-Z`. So if anything else appears in the output i should generate character once again, right? Thanks for whole your help. – peter Schiza Oct 28 '16 at 12:18
  • In the range {97,...,122}, there's not problem in casting `int`s to `char`s, and the casted `int`s will be exactly in set of `char`s that you want generate into, so you don't even need to reject and re generate, as what you will have generated will be a kosher `char` – Olórin Oct 28 '16 at 12:38
  • If that suits, don't forget to validate the answer ;-) – Olórin Oct 29 '16 at 09:41
0

While I'm all with using Binomial for letters sampling (you might to look at Poisson as well, but variance is a bit off, I think)

Wrt Laplace distribution, it could be constructed from c++11 standard pieces along the lines

std::default_random_engine generator;

template <typename gen> double
sample_laplace(double mu, double b, gen& generator) {
    std::uniform_real_distribution<double> rng(0.0, 1.0);

    double x = -std::log(1.0 - rng(generator)) * b;
    if (rng(generator) < 0.5)
        x = -x;

    return x + mu;
}
Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64