【问题标题】:How to sample without replacement using c++ uniform_int_distribution [duplicate]如何使用c ++ uniform_int_distribution进行采样而不进行替换[重复]
【发布时间】:2016-02-21 11:54:13
【问题描述】:

我想使用 c++ 随机库中的 uniform_int_distribution。但是,它只进行带替换的采样,如下例所示。如何在不更换的情况下进行采样?

#include <iostream>
#include <random>

int main()
{
  std::default_random_engine generator;
  std::uniform_int_distribution<int> distribution(1,4);

  for(int i=0; i<4; ++i)
    std::cout << distribution(generator) << std::endl;

  return 0;
}

【问题讨论】:

  • 你是什么意思,“替换”?

标签: c++ random


【解决方案1】:

如果您想从[low, high) 范围内采样N 均匀分布的整数而不进行替换,您可以这样写:

std::vector<int> array(N);   // or reserve space for N elements up front
 
auto gen = std::mt19937{std::random_device{}()};
    
std::ranges::sample(std::views::iota(low, high), 
                    array.begin(),
                    N, 
                    gen);

std::ranges::shuffle(array, gen);  // only if you want the samples in random order 

这是demo。

这类似于Philip M's answer,但从 C++20 开始可以延迟生成输入范围。

【讨论】:

    【解决方案2】:

    从 c++17 开始,现在有一个标准库函数可以做到这一点。见https://en.cppreference.com/w/cpp/algorithm/sample

    #include <iostream>
    #include <random>
    #include <string>
    #include <iterator>
    #include <algorithm>
    
    int main()
    {
        std::string in = "abcdefgh", 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';
    }
    

    【讨论】:

      【解决方案3】:

      在std::array&lt;int&gt; 或std::vector&lt;int&gt; 上使用std::shuffle,初始化为{1, 2, 3, 4}。

      然后依次读回容器内容。

      这将比绘制一个随机数并仅在之前未绘制过时才接受它具有更好的统计特性。

      参考http://en.cppreference.com/w/cpp/algorithm/random_shuffle

      【讨论】:

      • 我会改用std::shuffle。
      • 这是一个好点:在使用 C++11 时最好使用新函数。
      • 你能解释一下你的意思,更好的统计特性吗?假设您只需要两次绘制而不需要从一个大向量中进行替换。洗牌算法在向量的大小上将具有线性复杂性,而替代建议(如果已经绘制则绘制和拒绝)将是 O(1)。
      • @quant_dev 从这个意义上说,两种算法的统计属性将是相同的......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      相关资源
      最近更新 更多