离散分布 returns 个整数越界

discrete distribution returns integers out of bound

我写了下面的函数来采样而不用替换。它 return 是一个 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;
}

在我的应用程序中,我多次使用此采样,经过多次迭代后,离散分布 return 是一个大于包含概率的向量大小的整数。 (更准确地说,我的矢量大小为 178,我得到的是 return 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[=28的值=](变成无穷大),下面的计算就没有意义了。

我在这种特殊情况下测试了 gcc、clang 和 MSVC 的行为,发现虽然 gcc 和 clang 产生了一个所有概率都为零的分布,并且 std::discrete_distribution::operator() 总是 returns n - 1,MSVC 也产生一个所有概率都为零的分布,但是返回的整数总是n(超出范围的值,正如提问者所经历的那样)。

根据我的解释,这不是标准的合规行为,即使值得赞扬的是,OP 的输入参数导致违反先决条件。