4

我想生成0到5范围内的随机数,但是例如,在某些情况下我不需要数字3,我只需要0、1、2、4、5。如何生成范围内的随机数,但可以选择排除我不需要的数字。

4

6 回答 6

5

这是另一个使用 C++ 11 的现代特性的解决方案。

#include <functional>
#include <iostream>
#include <ostream>
#include <random>

int main()
{
    std::random_device rd;

    unsigned long seed = rd();
    std::cout << "seed " << seed << std::endl;

    std::mt19937 engine(seed);

    // Distribution  {0, 1, 2, 4, 5}
    std::discrete_distribution<> dist {{1, 1, 1, 0, 1, 1}};
    auto rng = std::bind(dist, std::ref(engine));

    const int n = 10;
    for (int i = 0; i != n; ++i)
    {
        int x = rng();
        std::cout << x << std::endl;
    }

    return 0;
}
于 2014-08-31T04:48:52.513 回答
2

您要排除的数字在编译时是否已知?然后一个简单的查找表应该做:

static int table[] = {0, 1, 2, 4, 5};
int index = rand() % (sizeof table / sizeof *table);
int number = table[index];

当然,rand()这是一个可怕的伪随机数生成器,但那是另一个话题。

于 2013-02-17T10:35:57.603 回答
0

只需在循环中丢弃 3:

template <typename Rng>
int rand_no_three (Rng& rng)
{
    std::uniform_int_distribution<> dist (0, 5);
    int c;

    do {
       c = dist (rng);
    } while (c == 3);

    return c;
}

示例用法:

std::mt19937 rng;
int c = rand_no_three (rng);
于 2013-02-17T10:33:42.653 回答
0

这是一种在没有查找表的情况下执行此操作的方法,以防您有内存限制。

int map_fun(int i)
{ 
  switch(i)
  {
    case 3: return 4;
    case 4: return 5;
  }
  return i;
}

int main()
{
   int i= map_fun(random_between(0, 4));
}
于 2013-02-17T10:40:51.250 回答
0

这是使用这篇文章中的 java 代码的示例:如何在一个范围内生成一个随机数但排除一些? 翻译成c++。

这有点通用,并且没有使用不必要的循环。

我还做了一个分布、范围和出现 - 检查这个程序:

#include <iostream>
#include <vector>
#include <cstdlib>
#include <time.h>
#include <map>
using namespace std;


int getRandomWithExclusion(int start, int end, vector<int> &excludes){
    unsigned int max = end - start + 1 - excludes.size();
    int random = start+(rand() % max);
    for (unsigned int i = 0;i<excludes.size();i++) {
        int ex = excludes[i];
        if (random < ex){
            break;
        }
        random++;
    }
    return random;
}

int main()
{
    srand (time(NULL));
    vector<int> excl;

    map<int,int> distMap;

    excl.push_back(-2);
    excl.push_back(3);




    for(int i=0;i<100000;i++){

        int val = getRandomWithExclusion(-5,5,excl);
        if (distMap.find(val) == distMap.end()){
            distMap[val]=0;
        }
        int key = distMap[val]+1;
        distMap[val]=key;
    }
    map<int, int>::iterator p;
    for(p = distMap.begin(); p != distMap.end(); p++) {
        cout << p->first <<" occurs " <<p->second << endl;

    }

    cout << "seems legit: even distributed and correct" << endl;

    return 0;
}
于 2013-02-17T11:12:00.563 回答
0

这个 c++ 函数应该处理这个任务:

int getRandomIntExcludingRange(int start, int end, int start_range, int end_range) {

    // handle bad input gracefully
    if (start > end) {
        std::swap(start, end);
    }
    if (start_range > end_range) {
        std::swap(start_range, end_range);
    }
    std::clamp(start_range, start, end);
    std::clamp(end_range, start, end);

    auto range_length = end_range - start_range;
    auto adj_end      = end - range_length;
    auto shifted_end  = adj_end - start;

    int rand_int = (rand() % shifted_end) + start;

    if (rand_int >= start_range) {
        rand_int = (rand_int - start_range) + end_range;
    }
    return rand_int;
}
于 2021-01-22T20:04:50.180 回答