离散分布 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 的输入参数导致违反先决条件。
我写了下面的函数来采样而不用替换。它 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 的输入参数导致违反先决条件。