【问题标题】:How to check to make sure there are no repeats when generating 6 random numbers?生成 6 个随机数时如何检查以确保没有重复?
【发布时间】:2019-06-15 08:56:16
【问题描述】:

我可以将随机数放入一个数组中,但我不知道如何检查以确保它们不会重复。我打印出代码,但数组中没有数字(什么都不打印)。

//puts random numbers into an array
i = 0, j = 0;
srand(time(NULL));
for (i = 0; i < arrSize; i++)
{
  randArr[i] = randNums(1,50);
}

i = 0;
for(i = 0; i < arrSize; i++)
{
  printf("%d ", randArr[i]);
}

printf("\n\n");

//checks to make sure there are no duplicates
i = 0, j = 0, k = 0, temp = 0;
for (i = 0; i < arrSize; i++)
{
  for (j = 1; j <= arrSize;)
  {
    if (randArr[j] == randArr[i])
    {
      for (k = j; k <= arrSize; k++)
      {
        temp = randNums(1,50);
        randArr[k + 1] = temp;
      }
      arrSize--;
    }
    else
      j++;
  }
}

//generates random numbers between the inputed max and min
int randNums(int min, int max)
{
  int result = 0, low = 0, high = 0;
  if (min < max)
  {
    low = min;
    high = max + 1;
  }
  else
  {
    low = max + 1;
    high = min;
  }
  result = (rand() % (high - low)) + low;
  return (result);
}

【问题讨论】:

  • 欢迎来到 SO。您应该给出一个最小的完整且可验证的示例。有关指南,请参阅 stackoverflow.com/help/mcve。它应该包括所有声明和您的主要声明。
  • @AlainMerigot 这只是我的一小部分代码,因为其他部分根本不影响这部分
  • 这通常是一个算法问题,有许多不同的解决方案和不同的权衡。您会在互联网上找到许多不同的方法,只需在此处链接 一些 源:geeksforgeeks.org/…
  • 我认为使用en.wikipedia.org/wiki/Poisson_distribution 重复然后随机排列值可能是最快的,但如果两个值相交,可以排序和重新滚动。
  • 我喜欢@Neil 的想法

标签: c arrays random numbers


【解决方案1】:

小心!这个问题有许多不同的解决方案,它们都有一个或另一个缺点。如果我要快速实现它,我会选择这样的东西(没有太多的C-magic):

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SIZE (30)
#define RAND_MIN (1)
#define RAND_MAX (50)

static int randNums(int min, int max) {
  // ...
}

int main(void) {
  (void) srand(time(NULL));
  int arr[SIZE];
  int used = 0;
  while (used < SIZE) {
    int  num    = randNums(RAND_MIN, RAND_MAX);
    bool exists = false;
    for (int i = 0; i < used; ++i) {
      if (arr[i] == num)
        exists = true;
    }
    if (exists == false)
      arr[used++] = num;
  }
  for (int i = 0; i < SIZE; ++i)
    (void) printf("%d\n", arr[i]);
  return EXIT_SUCCESS;
}

希望对你有帮助:)

【讨论】:

  • 还请注意,如果randNums() 中的数字少于SIZE,这将创建一个无限循环;如果这不仅仅是玩弄想法,那么您肯定会想预先验证这一点。
  • else { low = max + 1; high = min; } 出现混淆。我怀疑你想要else { low = max; high = min + 1; } 也有麻烦randNums(some_int, INT_MAX) 以及数学上max - min &gt; INT_MAX 的任何情况
  • 你当然是对的;使用 sarah 的“原样”部分,因为问题是关于唯一数字,而不是关于随机数生成。
【解决方案2】:

this answer,你可以做rejection sampling,但是固定数量的样本的均匀分布对于非常简单的哈希集来说是完美的。 (虽然渐近运行时可能与n=6 无关。)

#include <stdlib.h> /* (s)rand */
#include <stdio.h>  /* printf */
#include <time.h>   /* clock */
#include <assert.h> /* assert */

/* Double-pointers are confusing. */
struct Reference { int *ref; };

/* Simple fixed hash set. */
static struct Reference bins[256];
static int nums[6];
static const size_t no_bins = sizeof bins / sizeof *bins,
    no_nums = sizeof nums / sizeof *nums;
static size_t count_num;

/* Uniformly distributed numbers are great for hashing, but possibly clump
 together under linear probing. */
static size_t hash(const int n) { return ((size_t)n * 21) % no_bins; }

/* Linear probing. */
static struct Reference *probe(const int n) {
    size_t bin_index;
    struct Reference *bin;
    assert(sizeof bins > sizeof nums);
    for(bin_index = hash(n); bin = bins + bin_index,
        bin->ref && *bin->ref != n; bin_index = (bin_index + 1) % no_bins);
    return bin;
}

/* Return whether it's a new value. */
static int put_in_set(const int n) {
    struct Reference *bin = probe(n);
    int *num;
    assert(count_num < no_nums);
    if(bin->ref) return 0; /* Already in hash. */
    num = nums + count_num++;
    *num = n;
    bin->ref = num;
    return 1;
}

/* http://c-faq.com/lib/randrange.html */
static int rand_range(const unsigned n) {
    unsigned int x = (RAND_MAX + 1u) / n;
    unsigned int y = x * n;
    unsigned int r;
    assert(n > 0);
    do {
        r = rand();
    } while(r >= y);
    return r / x;
}

/* Generates random numbers between the inputed max and min without
 repetition; [min, max] inclusive. */
static int unique_uniform(const int min, const int max) {
    int n;
    assert(min <= max && (size_t)(max - min) >= count_num);
    do { n = rand_range(max - min + 1) + min; } while(!put_in_set(n));
    return n;
}

int main(void) {
    int n = 6;
    srand((int)clock()), rand(); /* My computer always picks the same first? */
    while(n--) { printf("%d\n", unique_uniform(1, 50)); }
    return EXIT_SUCCESS;
}

但是,如果数字密集,(例如,unique_uniform(1, 6),)它将拒绝很多数字。另一种解决方案是将Poisson 分布数字作为运行总和,(递归T(n+1)=T(n)+\mu_{n+1},)其中预期值是数字范围除以总样本,然后取random permutation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-21
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-03-06
    • 2016-04-13
    • 1970-01-01
    相关资源
    最近更新 更多