【问题标题】:Non-repeating random number generator in CC中的非重复随机数生成器
【发布时间】:2014-06-10 16:59:30
【问题描述】:

我想写一个程序,每次运行时打印出10个随机数,打印出的随机数应该是1-10,而且它们不应该重复。

更新:很抱歉没有说明确切的问题,基本上,假设只有在尚未使用随机数时才重新分配随机数的 while 循环导致我的程序根本不打印任何内容。如果我注释掉整个while循环并将printf留在底部,它会打印出1-10之间的10个随机数,但它只会打印出重复。

谁能告诉我如何修复我的代码或给我一些提示?

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

int main()
{
int array[10];
int x, p;
int count;
int i=0;

srand(time(NULL));

for(count=0;count<10;count++){
array[count]=rand()%10+1;
}

while(i<10){
int r=rand()%10+1;

for (x = 0; x < i; x++)
{
if(array[x]==r){
    break;
}
if(x==i){
    array[i++]=r;
}
}

}
for(p=0;p<10;p++){
printf("%d ", array[p]);
}
return 0;
}

【问题讨论】:

  • 搜索Linear Feedback Shift Registers (LFSR)Pseudo Random Number Generator (PRNG)
  • 同样在你的代码中,你也可以在第二个rand()之前使用srand()
  • 请提及您遇到的问题。
  • 听起来你需要shuffle 的值,然后遍历洗牌集。

标签: c random numbers


【解决方案1】:

使用移位掩码算法,您可以生成不重复的伪随机数。我已经包含了我的一个函数,在下面给出了一个例子。这个过程比任何其他提供的算法快 10 倍,并且不使用额外的内存。这种算法通常用于“数字溶解”和“散射”效果等,但我的实现侧重于单维效果。

享受, B博士

/* Bryan Wilcutt's random scatter algorithm */
/* Generates random-appearing, non-repeating values. */

/* Can be any number within the given range of 32K 
   Mask must be changed for other ranges.  */

#define START_POINT 1

void randScatter()
{
    long mask;  /* XOR Mask */
    unsigned long point;
    int val;
    unsigned int range = 0x7fff; /* 32K */

    mask = 0x6000; /* Range for 32K numbers */

    /* Now cycle through all sequence elements. */

    point = START_POINT;

    do {
        val = point % range;    /* Get random-appearing value */
        printf("%08x\n", val);

        /* Compute the next value */

        if (point & 1) {
            /* Shift if low bit is set. */

            point = (point >> 1) ^ mask;
        } else {
            /* XOR if low bit is not set */

            point = (point >> 1);
        }
    }  while (point != START_POINT); /* loop until we've completed cycle */
}

【讨论】:

    【解决方案2】:

    if(x==i)for (x = 0; x &lt; i; x++) 循环中永远不会为真,因此 while 循环永远不会终止。 if 语句必须移动到 for 循环之后:

    while(i<10){
        int r=rand()%10+1;
    
        for (x = 0; x < i; x++)
        {
            if(array[x]==r){
                break;
            }
        }
        if(x==i){
            array[i++]=r;
        }
    }
    

    也是第一个循环

    for(count=0;count<10;count++){
        array[count]=rand()%10+1;
    }
    

    是不必要的,因为这些值稍后会被覆盖。

    (如果您查找“随机排列”或“Fisher-Yates shuffle” 那么你会发现更有效的算法来产生非重复序列 随机数。)

    【讨论】:

      【解决方案3】:

      (1) 你的缩进是错误的。正确的应该是:

      #include <stdio.h>
      #include <time.h>
      
      int main()
      {
          int array[10];
          int x, p;
          int count;
          int i=0;
      
          srand(time(NULL));
      
          for(count=0;count<10;count++){
              array[count]=rand()%10+1;
          }
      
          while(i<10){
              int r=rand()%10+1;
      
              for (x = 0; x < i; x++)
              {
                  if(array[x]==r){
                      break;
                  }
                  if(x==i){
                      array[i++]=r;
                  }
              }
          }
          for(p=0;p<10;p++){
              printf("%d ", array[p]);
          }
          return 0;
      }
      

      (2)一旦缩进正确,就更容易看出问题。 if(x==i) 部分应在 while 内部,但在 for 外部。

      #include <stdio.h>
      #include <time.h>
      
      int main()
      {
          int array[10];
          int x, p;
          int count;
          int i=0;
      
          srand(time(NULL));
      
          for(count=0;count<10;count++){
              array[count]=rand()%10+1;
          }
      
          while(i<10){
              int r=rand()%10+1;
      
              for (x = 0; x < i; x++)
              {
                  if(array[x]==r){
                      break;
                  }
              }
              if(x==i){
                  array[i++]=r;
              }
          }
          for(p=0;p<10;p++){
              printf("%d ", array[p]);
          }
          return 0;
      }
      

      这会打印出正确的结果。

      (3) 您现在可以删除用重复填充数组的for(count=0;count&lt;10;count++) 部分。其结果被另一部分覆盖。


      道德说明:正确的格式实际上有助于发现错误。不要忽视它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-24
        • 1970-01-01
        • 2018-06-25
        • 2014-11-10
        • 2013-04-06
        • 1970-01-01
        相关资源
        最近更新 更多