Converting a Uniform Distribution to a Normal Dist

2019-01-01 04:57发布

How can I convert a uniform distribution (as most random number generators produce, e.g. between 0.0 and 1.0) into a normal distribution? What if I want a mean and standard deviation of my choosing?

15条回答
梦该遗忘
2楼-- · 2019-01-01 05:50

This is a Matlab implementation using the polar form of the Box-Muller transformation:

Function randn_box_muller.m:

function [values] = randn_box_muller(n, mean, std_dev)
    if nargin == 1
       mean = 0;
       std_dev = 1;
    end

    r = gaussRandomN(n);
    values = r.*std_dev - mean;
end

function [values] = gaussRandomN(n)
    [u, v, r] = gaussRandomNValid(n);

    c = sqrt(-2*log(r)./r);
    values = u.*c;
end

function [u, v, r] = gaussRandomNValid(n)
    r = zeros(n, 1);
    u = zeros(n, 1);
    v = zeros(n, 1);

    filter = r==0 | r>=1;

    % if outside interval [0,1] start over
    while n ~= 0
        u(filter) = 2*rand(n, 1)-1;
        v(filter) = 2*rand(n, 1)-1;
        r(filter) = u(filter).*u(filter) + v(filter).*v(filter);

        filter = r==0 | r>=1;
        n = size(r(filter),1);
    end
end

And invoking histfit(randn_box_muller(10000000),100); this is the result: Box-Muller Matlab Histfit

Obviously it is really inefficient compared with the Matlab built-in randn.

查看更多
孤独寂梦人
3楼-- · 2019-01-01 05:52

The Ziggurat algorithm is pretty efficient for this, although the Box-Muller transform is easier to implement from scratch (and not crazy slow).

查看更多
怪性笑人.
4楼-- · 2019-01-01 05:53

I would use Box-Muller. Two things about this:

  1. You end up with two values per iteration
    Typically, you cache one value and return the other. On the next call for a sample, you return the cached value.
  2. Box-Muller gives a Z-score
    You have to then scale the Z-score by the standard deviation and add the mean to get the full value in the normal distribution.
查看更多
登录 后发表回答