我想从一组频率中绘制一个数字,直到所有值都为零。通过绘制剩余数字的频率正在减少。在R中有一个“简单”的函数样本为我做。在C ++中,我找到了std :: discrete_distribution,但没有关于它的详细信息
实际上我将频率(由std :: vector保持)求和,直到随机数小于或等于。这是:
我希望能在你的帮助下找到更好的解决方案。
感谢您的时间,支持和答案:)
答案 0 :(得分:0)
C ++ 17为我们提供了std::sample
函数:
#include <iostream>
#include <random>
#include <string>
#include <iterator>
#include <algorithm>
int main()
{
std::string in = "abcdefgh";
std::string out;
std::sample(in.begin(), in.end(),
std::back_inserter(out),
5,
std::mt19937{std::random_device{}()} //(*)
);
std::cout << "five random letters out of " << in << " : " << out << '\n';
}
如果你没有C ++ 17,那么提案A sample Proposal, v4包含一个示例实现(使用uniform_int_distribution):
// the primary function, which calls the detailed functions depending on types of iterators in the used containers.
template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter sample( PopIter first, PopIter last, SampleIter out, Size n, URNG&& g )
{
using pop_t = typename std::iterator_traits< PopIter >::iterator_category;
using samp_t = typename std::iterator_traits< SampleIter >::iterator_category;
return __sample( first, last, pop_t{}, out, samp_t{}, n, forward< URNG >( g ) );
}
template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter __sample( PopIter first,
PopIter last,
std::input_iterator_tag,
SampleIter out,
std::random_access_iterator_tag,
Size n,
URNG&& g )
{
using dist_t = std::uniform_int_distribution< Size >;
using param_t = typename dist_t::param_type;
dist_t d{};
Size sample_sz{0};
while ( first != last && sample_sz != n )
out[ sample_sz++ ] = *first++;
for ( Size pop_sz{sample_sz}; first != last; ++first, ++pop_sz )
{
param_t const p{0, pop_sz};
Size const k{d( g, p )};
if ( k < n )
out[ k ] = *first;
}
return out + sample_sz;
}
template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter __sample( PopIter first,
PopIter last,
std::forward_iterator_tag,
SampleIter out,
std::output_iterator_tag,
Size n,
URNG&& g )
{
using dist_t = std::uniform_int_distribution< Size >;
using param_t = typename dist_t::param_type;
dist_t d{};
Size unsampled_sz = std::distance( first, last );
for ( n = min( n, unsampled_sz ); n != 0; ++first )
{
param_t const p{0, --unsampled_sz};
if ( d( g, p ) < n )
{
*out++ = *first;
--n;
}
}
return out;
}