如何在c++/java中生成一组遵循一定分布的值

How to generate a set of values that follow certain distribution in c++/java?

本文关键字:一组 分布 c++ java      更新时间:2023-10-16

例如,我有一个p.d.f f(x) = 1/25 - x/1250 (x = 0到50);我的问题是如何生成一组满足给定p.d.f的值。请给出一个关于如何在c++或java中实现的想法。非常感谢。

我不知道直接从pdf,但你可以转换pdf到cdf(通过积分),然后使用逆变换采样。这假设您有一种技术可以在[0, 1]中生成随机数u(例如Java中的Math.random())。

一旦您已经生成了这样一个u,找到一个x这样的cdf(x) = ux就是你想要的值

您的功能类似于f(x) := 1 - x。对于这种情况,我做了以下操作:

  1. 整合f功能生成F
  2. 将函数F归一化,使其域为[0;1),得到NF
  3. NF反向生成dist

然后使用以下代码检查结果:

package so7691025;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
public class DistImage {
  private static double dist(double x) {
    return 1.0 - Math.sqrt(1.0 - x);
  }
  public static void main(String[] args) throws IOException {
    final Random rnd = new Random(0);
    BufferedImage img = new BufferedImage(1000, 1000, BufferedImage.TYPE_BYTE_GRAY);
    int[] distrib = new int[1000];
    for (int i = 0; i < 500000; i++) {
      distrib[(int) (dist(rnd.nextDouble()) * 1000)]++;
    }
    Graphics g = img.getGraphics();
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, 1000, 1000);
    g.setColor(Color.BLACK);
    for (int i = 0; i < 1000; i++) {
      g.drawLine(i, 1000, i, 1000 - distrib[i]);
    }
    ImageIO.write(img, "png", new File("d:/distrib.png"));
  }
}

生成的图像对我来说非常好。

如果你的value -set是离散的,那么在文章"a Linear algorithm For generated Random Numbers With a Given Distribution"中描述了一个有效的算法。该算法包含一个简单的伪代码,时间为O(n),其中n为集合大小。

如果pdf不是离散的,如在您的示例中,请参见"蒙特卡罗模拟介绍"中的5.1节。