【问题标题】:generate random number in a range c++ [duplicate]在c ++范围内生成随机数[重复]
【发布时间】:2014-10-10 14:09:56
【问题描述】:

我正在使用 ncurses 库来构建游戏。我无法生成正确的随机数。下面的 while 循环需要不断生成随机数,直到它们介于 1 到 45 之间(这是我在标准屏幕上的 y 轴限制)。我无法弄清楚我做错了什么,因为 while 循环条件对我来说看起来不错。问题是while循环开始无限运行。我什么也没做,只是在最后打印生成的数字,因为我只想看到生成了正确的数字。谁能帮我解决这个问题?以下是我的主要内容。

int main()
{
int r,c,x=0;
initscr();
raw();
keypad(stdscr, TRUE);
noecho();
//mvprintw(22,45,"<");
getmaxyx(stdscr,r,c);

int n,n2 = 0;

while((n<1)||(n>45)){
srand (time(NULL));
n = rand();
srand (time(NULL));
n2 = rand();
}
mvprintw(4,10,"First Random Number: %d\n", n);
mvprintw(5,10,"Second Random number: %d\n", n2);

getch();
endwin();
return 0;
}

【问题讨论】:

  • 首先,不要多次调用srand,这样会得到很差的结果。其次,你为什么只调用普通的rand() 而不是(rand()%45)+1 之类的东西?
  • rand() 有很多问题,你可能会觉得这个lesinskis.com/code_repair_01_rand_problems.html 很有趣。
  • C 还是 C++?答案会千差万别。
  • 哦,是的.. 没有使用 srand 2 次。虽然它没有任何区别。我现在只是想得到一个合理的输出。我在改善 rand 结果方面没有做太多工作。但是是的,你是对的,这样做会改善 rand 结果。但是,现在我似乎无法跳出循环并显示结果。对此有什么想法吗?

标签: c++ c random


【解决方案1】:

在 C++ 中你可以这样做:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 gen( rd());
    std::uniform_int_distribution<> dis( 1, 45);

    for (int n=0; n<1000; ++n)
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

使用rand() % x 是一个有缺陷的设计,因为引入的偏差会不均匀地划分范围。您可以阅读this 了解更多关于rand() % x 引入的偏见。

【讨论】:

  • 在大多数情况下,rand() 就可以了。来自不平等划分的偏差很小,没有严重的分配要求,是无关紧要的。例如,让它从 45 个乐透号码中选择 6 个号码并不是真正的问题 :-) 不过,这是一个很好的答案,它显示了较新的 C++ 随机内容。
  • @paxdiablo 是的,你是对的,只是想警告...
  • @paxdiablo, rand() 应该避免。它不会生成随机数。
  • @CroCo 是的,但请记住,对于某些事情,应用程序就足够了
  • CroCo,Mersenne twister 也不生成随机数,这就是它们被称为伪随机数生成器的原因。它们的特性众所周知,适用于除最苛刻的用途之外的所有用途。
【解决方案2】:

您想在事情开始时调用srand 一次,然后使用模数将rand 结果带入您的范围,例如:

srand(time(NULL));
n  = rand() % 45 + 1;
n2 = rand() % 45 + 1;

【讨论】:

  • 由于偏差,这不提供均匀分布
  • @0d0a (问题的)作者没有说明他需要均匀分布
  • 但他认为这是随机对他来说意味着什么
  • @0d0a 我不明白-他只是说“实际上并不需要均匀分布”?那预期呢?
  • 错误,“实际上并不需要均匀分布” - OP 直接声明均匀分布无关紧要,或者在我看来就是这样 :-)
【解决方案3】:

就像@unholySheep 评论的那样,rand() 返回一个介于 0 和 RAND_MAX 之间的值,这是一个巨大的值。因此,您不太可能很快获得介于 1 和 RAND_MAX 之间的值。

因此,解决方法是按你想要的数字做除法提醒:

 n = 1 + rand() % 45;

你甚至不需要一段时间。

【讨论】:

【解决方案4】:

您可以通过以下方式获得 1 到 45 之间的随机数:

n = rand() % 45 + 1;

它在分布方面并不完美,但对于既不是统计学家也不是密码学家的人来说已经足够接近了,在这种情况下,您可能会使用真实随机数。

您还应该在程序开始的某个地方调用srand() 一次,而不是多次调用,尤其是在您使用当前时间播种时。

在同一秒内多次执行此操作会给您一个明确的非随机序列,例如:

42, 42, 42, 42, 42, 42, 42, ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 2012-09-30
    相关资源
    最近更新 更多