Search code examples
matlabstatisticsoctavenormal-distribution

Choosing from a range of numbers with normal distribution


I need to choose one pixel from a range of, for example, 0 to 1920 pixels with the normal distribution, but I have no idea how to do this in MatLab. I know that I can use normrnd() to retrieve a random value given mu and sigma, but how do I apply this to my situation?

mu might be at 500 pixels and sigma 100 pixels, for example.

My current approach is this

function xpos = apply_normal_distribution(mu, sigma, min_xpos=1, max_xpos=1920)
    % Applies normal distribution with median mu and standard deviation sigma
    % xpos will always be: min <= xpos <= max
    xpos = ceil(normrnd(mu, sigma));
    if xpos > max_xpos
        xpos = max_xpos;
    elseif xpos < min_xpos
        xpos = min_xpos;
    endif
end

So I'm just using normrnd and cutting off if the value is higher or lower than my bounds. Don't know how good this is, but it works.


Solution

  • The moment you bound a normal distribution (or filter its results in any other way) it is not a normal distribution anymore. However, there exists a truncated normal distribution which is the closest thing to what you are looking for. It has it's own set of properties which are similar to a normal distribution if the bounds are far away from the mean and you have a low variance. With Matlab you can make that with:

    mu = 500;
    sigma = 100;
    %truncate at 0 and 1920
    pd = truncate(makedist('Normal',mu,sigma),0,1920);
    % take some (10) samples
    samples = random(pd,10,1);
    

    Building it from scratch for Octave:

    Your self-made proposal has the problem that if a realisation is outside the bound, you set the value to the bound value. Therefore the bound value will be overly proportional chosen. A less dirty way is instead to just draw a fresh value. I don't have a working Octave, but something like this should do it:

    function xpos = apply_normal_distribution(mu, sigma, min_xpos=1, max_xpos=1920)
        % new realisations are drawn as long as they are outside the bounds.
        while xpos<min_xpos | xpos>max_xpos 
                xpos = ceil(normrnd(mu, sigma));
        end
    end
    

    Just as a warning: If it is unlikely that a realisation will be within the bounds then this may run for a very long time...