c++ - 离散分布返回整数超出范围

标签 c++ language-lawyer distribution sampling

我编写了下面的函数以进行采样而不进行替换。它返回一个vector<int>,代表在某些点中被选取的样本。作为输入,我有一个vector<double>,其中包含概率和所需样本大小的整数。对于功能,我使用离散分布:
http://www.cplusplus.com/reference/random/discrete_distribution/discrete_distribution/

vector<int> samplingwoutreplacement(vector<double> probs, int samplesize) {
    random_device rd;
    mt19937 generator(rd());
    vector<int> sample;
    sample.reserve(samplesize);
    for (int i = 0; i < samplesize; i++) {
        discrete_distribution<int> distribution(probs.begin(), probs.end());
        int currentpick = distribution(generator);
        if (currentpick >= probs.size()) {
            cout  << endl << "error: range overstepped; current pick is: " << currentpick << endl;
            cout << "probs.size = " << probs.size() << endl;
            for (int j = 0; j < probs.size(); j++) {
                cout << probs[j] << endl;
            }
        }
        probs[currentpick] = 0;
        sample.push_back(currentpick);
    }
    return sample;
}
在我的应用程序中,我多次使用此采样,并且在进行多次迭代之后,离散分布返回的整数大于包含概率的 vector 的大小。 (更确切地说,我的 vector 的大小为178,而我的返回值为178,但是应该得到介于0到177之间的整数。)如何发生这种情况?

最佳答案

在C++标准中,我们可以在26.6.8.6.1 [rand.dist.samp.discrete](重点是我的)上阅读有关std::discrete_distribution的信息。

A discrete_­distribution random number distribution produces random integers i, 0 ≤ i < n, distributed according to the discrete probability function P(i | p0, …, pn−1) = pi.

Unless specified otherwise, the distribution parameters are calculated as: pk = wk/S for k = 0, …, n−1, in which the values wk, commonly known as the weights, shall be non-negative, non-NaN, and non-infinity. Moreover, the following relation shall hold: 0 < S = w0 + ⋯ + wn−1.


询问者使用的某些权重(例如1.29272e + 308)太大,以至于它们的总和超出了double的范围,因此S的值(变为无穷大)和以下计算变得毫无意义。
我在这种极端情况下测试了gcc,clang和MSVC的行为,发现当gcc和clang生成所有概率等于零的分布,并且std::discrete_distribution::operator()始终返回n-1时,MSVC也会生成所有概率等于零的分布,但返回的整数始终为n(如问问者所遇到的超出范围的值)。
以我的解释,这不是标准的合规行为,即使值得赞扬的是,OP的输入参数导致违反了前提条件。

关于c++ - 离散分布返回整数超出范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63232392/

相关文章:

c++ - 如何更快地扫描数据CD?

c++ - PPM 将 char 转换为 int 授予负数

c++ - 如何避免多个 deleter lambda?

c++ - 了解追加模式下的闪存文件系统磨损

c++ - 静态 vector 内部数据布局 - `union` 与 `std::aligned_storage_t` - 巨大的性能差异

c++ - 可以构造一个空的 std::optional<T> 调用 T 的默认构造函数吗?

java - 高斯随机分布的 NaN 误差

c++ - 在不复制的情况下将指针传递给不相关但兼容的类型数组?

python - python中的指数分布随机生成器(日志函数)?

matlab - 为什么在测试分布时 p 值为 0