如何生成满足泊松分布的随机数

时间:2015-10-31 14:04:18

标签: algorithm matlab statistics probability

我想通过使用组合方法生成500,000个随机数的泊松分布lambda = 1T=6,其描述如下:

  1. 生成均匀的r.v. z1z2,...
  2. z1.z2..zm<=exp(-lamda*T)
  3. 时停止
  4. 分配k = m – 1
  5. 然后计算10个区间([0,1][2,3],...,[16,17][18,∞)]中每个区间的数量。

    我知道MATLAB有一个内置函数poissrnd用于上述任务。但是,我想用上面的算法自己做。我尝试过并将其与poissrnd函数的结果进行比较,但我的代码给出了错误的结果。你能看一下我的代码并给我一些评论吗?

    num_generated = 500000;
    lambda=1;T=6;
    k_vec=[]; %% Store k
    for i=1:number_generated
        multiple=1;
        for j=1:number_generated
            %% Step 1: Generate uniform in the interval [0,1]: z1,z2...
            z=rand(); 
            %% Step 2: Stop when z1z2...zm<=exp(-lambda*T)
            multiple=multiple*z;
            if(multiple<=exp(-lambda*T))
                k=j-1;
                k_vec=[k_vec k]; % Record k in vec
                break;
            end
        end
    end
    range_1 = sum( k_vec(:)==0 )+sum(k_vec(:)==1) % # number with in range [0,1]
    range_2 = sum( k_vec(:)==2 )+sum( k_vec(:)==3) % # number with in range [2,3]
    range_3 = sum( k_vec(:)==4 )+sum( k_vec(:)==5) % # number with in range [4,5]
    range_4 = sum( k_vec(:)==6 )+sum( k_vec(:)==7) % # number with in range [6,7]
    range_5 = sum( k_vec(:)==8 )+sum( k_vec(:)==9) % # number with in range [8,9]
    range_6 = sum( k_vec(:)==10 )+sum( k_vec(:)==11) % # number with in range [10,11]
    range_7 = sum( k_vec(:)==12 )+sum( k_vec(:)==13) % # number with in range [12,13]
    range_8 = sum( k_vec(:)==14 )+sum( k_vec(:)==15) % # number with in range [14,15]
    range_9 = sum( k_vec(:)==16 )+sum( k_vec(:)==17) % # number with in range [16,17]
    range_10 = sum(k_vec(:)>=18)         % # number with in range [18,+infty)
    

2 个答案:

答案 0 :(得分:4)

您不知道multiple收敛需要多少随机值,因此您需要将for循环更改为j到一个持续时间较长的while循环为multiple > exp(-lambda*T)

通过将其更改为while循环,您现在需要k作为计数器并在循环的每次迭代中递增它:

(警告:未经测试的代码)

for i = 1:number_generated
    multiple = 1;
    k = 0;   %// Initialize counter for each number generated
    while multiple > exp(-lambda*T)   %// replace `for` loop
        k = k + 1;    %// Increment counter
        %% Step 1: Generate uniform in the interval [0,1]: z1,z2...
        z = rand(); 
        %% Step 2: Stop when z1z2...zm<=exp(-lambda*T)
        multiple = multiple*z;
    end
    %// If we exit the loop, we know multiple <= exp(-lambda*T)
    k = k - 1;
    k_vec = [k_vec k]; % Record k in vec
end

您还应该使用range_1range_2之类的顺序变量名来避免不惜一切代价 ... Matlab旨在处理数组和矩阵,因此您应该使用他们。在你的情况下,没有循环或矢量化的最简单的方法是:

range(1) = sum(...
range(2) = sum(...
...
range(10) = sum(...

现在你的工作区中有一个变量而不是10个,你对这个变量执行的任何操作都会容易得多。

答案 1 :(得分:1)

我不使用Matlab,因此我无法为您提供修复的确切语法。至少,您似乎忘记为每个新Poisson重置multiplek。此外,您只生成一个z

获得num_generated Poisson结果的工作实现应该类似于以下伪代码:

threshold = Math.exp(-lambda * T)
loop num_generated times {
    %% Each time through this loop produces a single Poisson outcome 
    count = 0
    product = 1.0
    while (product = product * rand()) >= threshold {
      count += 1
    }
    %% count now has a valid Poisson value, do what you want with it
}