我正在尝试使用<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;
}
请注意不对称性,尤其是结尾处的零。我看不到我做错了什么。代码是否有问题,或者发生了一些我看不到的舍入。谢谢。
答案 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的值被打印为零,因此我认为取消是问题所在。