使用rand函数随机分配值

时间:2016-02-25 17:21:19

标签: c

我正在做作业。我把rand函数放在一个循环中。

int counter = 1;

while ( counter <= 10 ){
   variable1 = rand() % 5 + 1;
   printf("%d", variable);
   counter = counter + 1;

在这段代码中,rand函数将不同的值赋给名为variable1的变量,但有时它会赋予相同的值,因为rand函数的范围很窄。如何执行该rand函数在每次循环返回时为变量分配不同的数字。

4 个答案:

答案 0 :(得分:1)

虽然rand()不是最大的随机函数,但它应该可以解决许多工作,当然也适用于大多数作业。从随机函数连续两次返回相同的数字是完全有效的 - 因为该函数不应该记录先前返回的值。

理解这一点的最好方法是举一个掷硬币的例子。每次抛硬币都是随机的,硬币没有前一次折腾的记忆,因此可以连续翻转硬币32次并且它们全部出现head - 如果每次抛硬币都有点一个32位整数,你已经创建了整数零的二进制值。

然而,人们倾向于认为(直觉)对于一个随机函数来说,不止一次返回相同的值是“错误的” - 但是我们的直觉在这个问题上是错误的。

如果由于某种原因想要不重复从一个循环到下一个循环的数字,那么无论您使用哪种随机函数,都需要编程 - 因为任何随机函数能够返回两次相同的值。

所以像这样的事情会这样做;

int counter = 1;
int prevValue = -1;

while ( counter <= 10 ){
   do {
      variable1 = rand();
   } while (variable1 == prevValue);
   prevValue = variable1;

   variable1 = variable1 % 5 + 1;
   printf("%d", variable);
   counter = counter + 1;
}

请注意,这仍然能够两次打印相同的值,因为10和15将是%5之前的不同值,但之后会相同。如果您希望考虑%5,那么printf永远不会连续两次打印相同的值,您需要在循环内移动%5。

答案 1 :(得分:0)

在你的代码片段中,我无法找到哪条指令是最后一条指令。如果你想在每个程序运行时获得不同的数字,你应该在while之前使用srand()函数。

但正如你之前提到的那样。您的范围(1 - 5)将缩小以每次获得10个唯一值。

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

int main(void) {
  int counter = 1;
  int variable1 = 0;


  srand(time(NULL));

  while ( counter <= 10 ) {
    variable1 = rand() % 5 + 1;
    printf("%d ", variable1);
    counter = counter + 1;
  }
  putchar('\n');

  return 0;
}

答案 2 :(得分:0)

为了生成随机数的唯一列表,您必须根据先前生成的数字列表检查生成的每个数字,以确保没有重复。最简单的方法是将先前生成的数字存储在数组中以进行检查。然后,您只需迭代数组中的值,如果您的最新数字已经存在,则创建一个新数字。

例如,您可以使用简单的标记来检查您是done。 e.g。

    while (counter < MAXI){
        int done = 0;
        while (!done) {           /* while done remains 0 (not done) */
            done = 1;
            tmp = rand() % MAXI + 1;        /* generate radom number */
            for (i = 0; i < counter; i++)   /* check again previous  */
                if (tmp == array[i])        /* if num already exists */
                    done = 0;               /* set as (not done)     */
        }
        array[counter++] = tmp;             /* assign random value   */
    }

或者您可以使用旧忠实的goto来做同样的事情:

    while (counter < MAXI) {
      gennum:  
        tmp = rand() % MAXI + 1;
        for (i = 0; i < counter; i++)
            if (tmp == array[i])
                goto gennum;
        array[counter++] = tmp;
    }

无论哪个对你更有意义。汇总一个完整的例子,你可以这样做:

#include <stdio.h>
#include <stdlib.h> /* for rand */
#include <time.h>   /* for time */

enum { MAXI = 10 };

int main (void) {

    int array[MAXI] = {0}, counter = 0, i, tmp;

    srand (time (NULL));    /* initialize the semi-random number generator */

    while (counter < MAXI){
        int done = 0;
        while (!done) {           /* while done remains 0 (not done) */
            done = 1;
            tmp = rand() % MAXI + 1;        /* generate radom number */
            for (i = 0; i < counter; i++)   /* check again previous  */
                if (tmp == array[i])        /* if num already exists */
                    done = 0;               /* set as (not done)     */
        }
        array[counter++] = tmp;             /* assign random value   */
    }

    for (i = 0; i < MAXI; i++)
        printf (" array[%2d] = %d\n", i, array[i]);

    return 0;
}

注意:您的mod%)所生成数字的数字必须等于或大于您打算收集的数量 - 否则,您无法生成唯一列表。)

示例使用/输出

$ ./bin/randarray
 array[ 0] = 8
 array[ 1] = 2
 array[ 2] = 7
 array[ 3] = 9
 array[ 4] = 1
 array[ 5] = 4
 array[ 6] = 3
 array[ 7] = 10
 array[ 8] = 6
 array[ 9] = 5

改组序列

鉴于评论中的讨论,提出了一个很好的观点,关于你的目标是创建一组独特的随机数(上图)还是一组数字中的随机集(例如任何序列,比如1-50在洗牌顺序)。如果您正在寻找后者,那么创建混洗序列的有效方法是使用修改后的Fisher-Yates shuffle知道为The "inside-out" algorithm

该算法允许使用来自任何数字源的混洗序列填充未初始化的数组(无论源是否可以是任何生成数字的方式)。本质上,该函数将当前索引处的数组中的值与随机生成的索引处保存的值进行交换。实现看起来像:

/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
    int i, val;
    for (i = 0; i < n; i++) {
        val = i ? randhq (i) : 0;
        if (val != i)
            a[i] = a[val];
        a[val] = i;         /* i here can be any source, function, etc.. */
    }
}

(其中randhq是生成随机值(0 <= val < n)

的任何函数

使用上述函数生成来自0 - (n-1)的值的混洗数组的简短示例程序如下所示。该示例使用由内向外算法在array中生成一个混洗的值序列,然后通过对数组进行排序来确认序列生成:

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

void insideout_fill (int *a, int n);
int randhq (int max);
void prnarray (int *a, size_t n, size_t strd, int wdth);
int intcmp (const void *a, const void *b);

int main (int argc, char **argv) {

    srand (time (NULL));
    int arrsz = argc > 1 ? (int)strtol (argv[1], NULL, 10) : 50;
    int array[arrsz];

    insideout_fill (array, arrsz);
    printf ("\n array initialized with inside-out fill:\n\n");
    prnarray (array, arrsz, 10, 4);

    qsort (array, arrsz, sizeof *array, intcmp);
    printf ("\n value confirmation for inside-out fill:\n\n");
    prnarray (array, arrsz, 10, 4);

    return 0;
}

/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
    int i, val;
    for (i = 0; i < n; i++) {
        val = i ? randhq (i) : 0;
        if (val != i)
            a[i] = a[val];
        a[val] = i;      /* i here can be any source, function, etc.. */
    }
}

/** high-quality random value in (0 <= val <= max) */
int randhq (int max)
{
    unsigned int
        /* max <= RAND_MAX < UINT_MAX, so this is okay. */
        num_bins = (unsigned int) max + 1,
        num_rand = (unsigned int) RAND_MAX + 1,
        bin_size = num_rand / num_bins,
        defect   = num_rand % num_bins;

    int x;
    /* carefully written not to overflow */
    while (num_rand - defect <= (unsigned int)(x = rand()));

    /* truncated division is intentional */
    return x/bin_size;
}

/** print array of size 'n' with stride 'strd' and field-width 'wdth' */
void prnarray (int *a, size_t n, size_t strd, int wdth)
{
    if (!a) return;
    register size_t i;

    for (i = 0; i < n; i++) {
        printf (" %*d", wdth, a[i]);
        if (!((i + 1) % strd)) putchar ('\n');
    }
}

/** qsort integer compare */
int intcmp (const void *a, const void *b)
{
    return *((int *)a) - *((int *)b);
}

示例使用/输出

$ ./bin/array_io_fill

 array initialized with inside-out fill:

   40   15   35   17   27   28   20   14   32   39
   31   25   29   45    4   16   13    9   49    7
   11   23    8   33   48   37   41   34   19   38
   24   26   47   44    5    0    6   21   43   10
    2    1   18   22   46   30   12   42    3   36

 value confirmation for inside-out fill:

    0    1    2    3    4    5    6    7    8    9
   10   11   12   13   14   15   16   17   18   19
   20   21   22   23   24   25   26   27   28   29
   30   31   32   33   34   35   36   37   38   39
   40   41   42   43   44   45   46   47   48   49

仔细看看,如果您有任何问题,请告诉我。

答案 3 :(得分:0)

  

如何执行rand函数在每次循环返回时为变量分配不同的数字?

我认为这意味着OP不想连续两次生成相同的数字。

在后续迭代中,使用%(n-1)

int main(void) {
  int counter;
  int variable;
  for (counter = 1; counter <= 10; counter++) {
    // First time in loop
    if (counter <= 1) {
      variable = rand() % 5 + 1;

    } else {
      int previous = variable;
      variable = rand() % (5 - 1) + 1;
      if (variable >= previous) variable++;
    }

    printf("%d\n", variable);
  }
  return 0;
}