离散分布不对称

时间:2018-07-02 16:39:47

标签: c++ probability-distribution

我正在尝试使用<div> Test: </div> <br> <ol> <li> One </li> <li> Two </li> </ol> 函数对离散分布进行采样。这是一个mwe:

std::discrete_distribution

这给出了:

// discrete_distribution
#include <iostream>
#include <random>

int main()
{
  const int nrolls = 10000; // number of experiments
  const int nstars = 100;   // maximum number of stars to distribute
  std::vector<double> weights;
  weights = {1.28503e-22, 1.67881e-17, 8.99861e-13, 1.70418e-08, 9.27031e-05,
    0.106935, 16.1967, 140.325, 16.1967, 0.106935, 9.27031e-05, 1.70418e-08,
    8.99861e-13, 1.67881e-17, 1.28503e-22};

  std::default_random_engine generator;
  std::discrete_distribution<int> distribution(weights.begin(), weights.end());

  for (double x:distribution.probabilities()) std::cout << x << " ";
  std::cout << std::endl;

  int p[15]={};

  for (int i=0; i<nrolls; ++i) {
    int number = distribution(generator);
    ++p[number];
  }

  std::cout << "a discrete_distribution:" << std::endl;
  for (int i=0; i<15; ++i)
    std::cout << i << ": " << std::string(p[i]*nstars/nrolls,'*') << std::endl;

  return 0;
}

请注意不对称性,尤其是结尾处的零。我看不到我做错了什么。代码是否有问题,或者发生了一些我看不到的舍入。谢谢。

1 个答案:

答案 0 :(得分:0)

问题似乎是浮点数学。特别是,分布似乎在保持权重正常化的同时保持了运行总和,最终使其失去了很小的概率。在一个简单的示例中,假设double只能存储2个有效数字(实际值接近16),并且您的权重分别为0.001、1.0、1.0和0.001:

它将权重总和为2.002(它只能表示为2.00),然后继续进行权重标准化。第一个变为0.001 / 2.00 = 0.0005。然后下一个是0.5,总计为0.5005(即5.00)。第三权重也是0.5,因此总和为1.00。允许的总和之差为0.00,因此不能为最后一个事件赋予正的权重。

我知道这不是一个完美的例子(因为权重仍未完全累加),但我希望您能理解这一点-您的标准库实现和/或您的浮点设置会弄乱您的结果这里由于取消。并不是说发生概率为1e-20的事件是在理性范围之内的,而是理论上应该保持对称性是正确的。

对于那些说“没有足够的精度来打印它”的人:我不同意,因为理想情况下这些值应该仍然是对称的,并且第一个值不像最后一个那样打印为0。看到,那些小于1且小于1的ULP的值被打印为零,因此我认为取消是问题所在。