【问题标题】:How to make a roll_die() function with an optional random seed parameter如何使用可选的随机种子参数制作 roll_die() 函数
【发布时间】:2019-03-03 16:18:08
【问题描述】:

C++ 新手。我想做一个像roll_die(unsigned int seed = ???) 这样的函数,默认情况下,该函数使用srand(time(NULL)) 在返回值之前为RNG 播种,但也允许用户指定种子。这就是我的作品

#include <iostream>
#include <ctime>

int roll_die(unsigned int seed = 0){
    // Returns a random integer between 1 and 6
    // time(NULL) is the number of seconds since 00:00 hours, Jan 1, 1970 UTC

    // Logic
    srand(seed);
    int randnum = rand();

    // Print what's going on
    std::cout << "The random seed is: " << seed << std::endl;
    std::cout << "The max random number is: " << RAND_MAX << std::endl;
    std::cout << "The randomly chosen number is: " << randnum <<std::endl;

    // Return the result
    int result = randnum % 6 + 1;
    return result;
}

这很好,但它不默认为 随机 种子。如果我尝试做类似int roll_die(unsigned int seed = time(NULL)){...} 的事情,我会收到警告

Unable to parse C++ default value 'time(NULL)' for argument seed of function roll_die

我假设是因为 time(NULL) 不返回 int。

这样做的正确方法是什么?

【问题讨论】:

  • @Slava 虽然欺骗是 OP 必须处理的事情,但这并不是问题所在。他们有 2 个问题,并在您为问题 2 关闭它时询问问题 1。我不确定它是否应该按原样关闭
  • @NathanOliver 我认为它涵盖了 OP 的所有问题——这个函数根本不应该调用 srand() 。正确的方法是在 main 中调用srand(),dup 完美地解释了它。
  • @Ben 你的返回随机数的函数根本不应该调用 srand() 并且 dup 解释了原因。
  • @Slava 而被骗目标如何回答?
  • 我觉得Converting time_t to int这个问题真的很接近你想要的。

标签: c++


【解决方案1】:

你想要的是:

void roll_die(unsigned int seed = static_cast<unsigned int>(time(NULL)))

基本上,您只需要告诉编译器将 time_t 转换为正确的时间。

但是,请务必考虑不要在每次投掷时都播种。查看其他答案。

【讨论】:

  • 宾果游戏。 (@user4581301 在 cmets 中指出这一点的道具。)
【解决方案2】:
int roll_die(unsigned int seed = 0){
  srand(seed);

这是代码异味。

每次掷骰子时都不会srand

您应该为随机数生成器播种,然后从中生成随机数流。

现代 C++ 方法是将随机值生成拆分为生成器和分布。

Generators 是熵所在的位置,并产生位。

Distributions 使用生成器并生成随机值。

srandrand 的 C 方法会导致大型程序出现问题。其中一些问题对于“全局状态”函数很常见(线程、使用引擎的两段代码之间的干扰等),还有一些是由于许多 srandrand 函数支持的质量差.

int roll_die(
  std::mt19937& engine
){
  auto rand = [&engine]{
    return std::uniform_int_distribution<>{1,6}(engine);
  };
  int result = rand();
  return result;
}
// very inefficient
int roll_die() {
  std::random_device d;
  std::mt19937 engine(d());
  return roll_die(engine);
}

请注意,我不使用%6 来生成值;不会产生统一的值。

我建议不要使用roll_die 的零过载版本。每卷都去std::random_device 是很昂贵的。使用更糟糕的东西(比如以秒为单位的当前时间)更糟糕,因为同一秒内的两次掷骰会产生相同的掷骰。

真的,你应该在某个地方做一个random_device,用它来播种你的std::mt19937,并在你的程序/模拟/等的生命周期内重复使用std::mt19937

您还应该记录使用的种子并提供输入种子的选项。这将使您能够创建可重复的模拟并更好地重现错误。

【讨论】:

    猜你喜欢
    • 2020-11-16
    • 2013-03-27
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2021-05-15
    相关资源
    最近更新 更多