【问题标题】:Generating random numbers in C++ using std::random_device使用 std::random_device 在 C++ 中生成随机数
【发布时间】:2017-07-31 20:54:25
【问题描述】:

我使用以下代码在 C++ 中生成随机数

std::random_device rdev {};
std::default_random_engine generator {rdev()};
std::uniform_int_distribution dist {a, b};

同样

std::default_random_engine generator {std::random_device{}()};
std::uniform_int_distribution dist {a, b};

我想了解的是使用种子值生成引擎背后的机制。 random_device 使用操作系统中的各种信息获取种子。该值用于初始化引擎对象。对于这里给出的第一个 sn-p 代码,如果 rdev 是一个对象,为什么我们将该值作为 rdev() 传递给引擎。为什么我们在类的对象上使用函数表示法?

对于第二个sn-p的代码,我们如何仅使用类名生成std::random_device对象?

我不确定我的理解问题是特定于随机数生成还是涉及 C++ 语言本身的更大问题。

【问题讨论】:

  • “对于第二个 sn-p 代码,我们如何仅使用类名生成 std​​::random_device 对象?” - 因为你是只使用类名。 {} 的尾随集是有原因的。
  • 更多的是关于 C++ 语言。您可以应用() 运算符的对象称为functors,您可以通过查看一些实例化对象的方法来回答您的大多数其他查询。
  • "为什么我们在类的对象上使用函数符号?" 这是一个运算符。

标签: c++ random


【解决方案1】:

std::random_device 对象本身不用作种子。 random_device 是一个真随机数生成器。调用它的括号运算符会从中产生一个样本。不幸的是,生成真正的随机数往往比生成伪随机数更昂贵,因此作为一种折衷方案,人们倾向于生成一个真正的随机数作为种子传递给伪随机生成器。因此,在您的第一个示例中,random_device 通过调用其括号运算符 (rdev()) 进行一次采样,返回一个真正的随机值,该值用作 std::default_random_engine 对象的种子。

第二个例子做同样的事情,除了在这种情况下random_device 是一个临时的。在 C++ 中,您可以通过直接调用类的构造函数来构造临时对象,在这种情况下使用大括号初始化。换句话说,表达式 std::random_device{} 返回一个临时的、默认构造的 random_device 对象,然后像前面的示例一样调用其括号运算符以生成种子。

【讨论】:

    【解决方案2】:

    std::random_device 重载了括号运算符,使其具有类似函数的语法。它或多或少看起来像这样:

    class random_device {
        /*...*/
    public:
        uint32_t operator()() {
            return /*...*/;
        }
    };
    

    然后可以在对象上调用它

    std::random_device device;
    uint32_t value = device();
    

    或在临时(技术上仍然是一个对象)上

    uint32_t value = std::random_device{}();
    uint32_t value_2 = std::random_device()(); //Equivalent syntax
    

    operator() 重载也可以通过其他方式重载。

    struct multiplies_by_3 {
        uint32_t operator()(uint32_t value) const {
            return value * 3;
        }
    };
    
    multiplies_by_3 multiplier;
    uint32_t value = multiplier(15); //45
    uint32_t value_2 = multiplies_by_3{}(20); //60
    uint32_t value_3 = multiplies_by_3()(25); //75
    
    struct subtracts_first_from_second {
        uint32_t operator()(uint32_t first, uint32_t second) const {
            return second - first;
        }
    };
    
    subtracts_first_from_second subtractor;
    uint32_t value = subtractor(15, 17); //2
    uint32_t value_2 = subtracts_first_from_second{}(20, 29); //9
    uint32_t value_3 = subtracts_first_from_second()(25, 17); //Underflows to some large number
    

    【讨论】:

      猜你喜欢
      • 2020-06-12
      • 2020-01-15
      • 1970-01-01
      • 2012-08-02
      • 1970-01-01
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      相关资源
      最近更新 更多