【问题标题】:Is there a faster way, to get random numbers, from a specific pool of numbers有没有更快的方法从特定的数字池中获取随机数
【发布时间】:2019-07-26 05:29:12
【问题描述】:

我正在寻找一种更快的方法,它允许我从存储在数组中的某个数字池中获取一个随机数。

我需要多次使用该方法,而当前方法严重拖慢了代码速度。

#include <cstdlib>
#include <ctime>

int main()
{      
    const int size = 8;
    int numberArray[size] = { 0, 0, 3, 4, 0, 6, 7, 0 };
    srand(time(0));

    int rndIndex;
    int rndNumber;
    do 
    {
        rndIndex = rand() % size;
        rndNumber = numberArray[rndIndex];
    } while (rndNumber <= 0);
}

我喜欢从数组中得到一个随机数,除了随机数小于0

【问题讨论】:

  • 为什么数组中有那些 0?
  • 随机性会受到零的影响。
  • 创建非零列表怎么样?
  • 我正在编写骑士之旅(en.wikipedia.org/wiki/Knight%27s_tour),这个数组代表骑士可能的移动,0代表一个移动,这是不可能的,因为边缘,或者领域已经通过了
  • 如果代码在你得到零时什么都不做,我要做的第一件事就是创建一个没有零的较小数组,然后简单地使用 rnd Index = rand() % size_without_zero

标签: c++ random srand


【解决方案1】:

如果我理解正确,那么您想从numberArray 中反复选择一个非零数字,但数组中的数字在每次选择后都会发生变化(因为骑士移动到具有不同移动选项的不同方格)。但是随着骑士的前进,您当前的解决方案会变得越来越慢,因为移动数组中的零越来越多,因此您必须循环更多次才能选择非零值。

我看到,解决这个问题的一个方法是首先计算数组中非零元素的数量。然后随机选择 (n) 直到该数字,最后选择数组中的第 n 个非零数字。此处显示想法的快速代码:

const int size = 8;
int numberArray[size] = { 0, 0, 3, 4, 0, 6, 7, 0 };
srand(time(0));

int numNonZero = 0;
for (int i = 0; i < size;++i) {
    if (numberArray[i] > 0)
        ++numNonZero;
}

int selectionNum;
int rndNumber;

selectionNum = rand() % numNonZero;

for (int i = 0; true; ++i) {
    rndNumber = numberArray[i];
    if (rndNumber > 0 && selectionNum-- == 0)
        break;
}

这会交换随机数量的循环,每个循环都有一个 rand() 抽奖,两个循环最多 8 个元素和一个 rand() 抽奖。

顺便说一句!

由于我已经输入了这个,我只想提一下rand() % X 是一种过时的生成随机数(0 到 X-1)的方法,而 STL 现在有更好的方法。

更好的方法是这样做:

const int size = 8;
int numberArray[size] = { 0, 0, 3, 4, 0, 6, 7, 0 };
std::random_device rd;
std::mt19937 mt(rd());  // initialize the random generator

int numNonZero = 0;
for (int i = 0; i < size;++i) {
    if (numberArray[i] > 0)
        ++numNonZero;
}

int selectionNum;
int rndNumber;

std::uniform_int_distribution<int> distribution(0, numNonZero - 1); // Set the distribution: 0 to numNonZero-1, both inclusive
selectionNum = distribution(mt);  // Generate random number in the selected range

for (int i = 0; true; ++i) {
    rndNumber = numberArray[i];
    if (rndNumber > 0 && selectionNum-- == 0)
        break;
}

您可以在此处阅读更多信息:http://www.cplusplus.com/reference/random/ 或此处Generate random numbers using C++11 random library

【讨论】:

  • 我也想继续阵列以删除零,但问题是您必须至少处理整个阵列一次。因为在数组被处理之前你不知道你有多少个零。并且处理的持续时间相当于 OP 的代码。见this benchmark
  • “更好的方法...”:这取决于您对“更好”的定义。看看你必须跳过哪些箍以避免使用 rand!
猜你喜欢
  • 1970-01-01
  • 2022-09-30
  • 2018-09-08
  • 2021-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-08
  • 2011-04-07
相关资源
最近更新 更多