Nếu trọng số của bạn thay đổi chậm hơn so với khi được vẽ, thì C ++ 11 discrete_distribution
sẽ là cách dễ nhất:
#include <random>
#include <vector>
std::vector<double> weights{90,56,4};
std::discrete_distribution<int> dist(std::begin(weights), std::end(weights));
std::mt19937 gen;
gen.seed(time(0));//if you want different results from different runs
int N = 100000;
std::vector<int> samples(N);
for(auto & i: samples)
i = dist(gen);
//do something with your samples...
Tuy nhiên, lưu ý rằng c ++ 11 discrete_distribution
tính toán tất cả các tổng tích lũy khi khởi tạo. Thông thường, bạn muốn điều đó vì nó tăng tốc thời gian lấy mẫu với chi phí O (N) một lần. Nhưng đối với một phân phối thay đổi nhanh chóng, nó sẽ phải chịu một chi phí tính toán (và bộ nhớ) lớn. Ví dụ: nếu các trọng số đại diện cho số lượng mục có và mỗi khi bạn vẽ một mục, bạn loại bỏ nó, bạn có thể sẽ muốn một thuật toán tùy chỉnh.
Câu trả lời của Will https://stackoverflow.com/a/1761646/837451 tránh được chi phí này nhưng sẽ chậm hơn so với C ++ 11 vì nó không thể sử dụng tìm kiếm nhị phân.
Để thấy rằng nó làm được điều này, bạn có thể xem các dòng liên quan ( /usr/include/c++/5/bits/random.tcc
trên bản cài đặt Ubuntu 16.04 + GCC 5.3 của tôi):
template<typename _IntType>
void
discrete_distribution<_IntType>::param_type::
_M_initialize()
{
if (_M_prob.size() < 2)
{
_M_prob.clear();
return;
}
const double __sum = std::accumulate(_M_prob.begin(),
_M_prob.end(), 0.0);
// Now normalize the probabilites.
__detail::__normalize(_M_prob.begin(), _M_prob.end(), _M_prob.begin(),
__sum);
// Accumulate partial sums.
_M_cp.reserve(_M_prob.size());
std::partial_sum(_M_prob.begin(), _M_prob.end(),
std::back_inserter(_M_cp));
// Make sure the last cumulative probability is one.
_M_cp[_M_cp.size() - 1] = 1.0;
}