【问题标题】:Random numbers with different output具有不同输出的随机数
【发布时间】:2013-11-26 10:19:43
【问题描述】:

我尝试随机抽取 20 个具有不同输出的数字,但它仍然包含相同的数字。 代码如下:

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

void main(){
    int arr[20];
    srand(time(NULL));
    int temp;

    temp=rand()%20;

    int x=0;



      while(x<20)
      {
          if(x==0)
          {
              arr[x]=temp;
              x++;
          }
          else
          {
                  for(int j=1;j<=x;j++)
                  {
                     do
                      {
                          temp=rand()%20;  
                      } while(temp==arr[x-j]);
                  }
                  arr[x]=temp;
                  x++;
           }
      }

      for(int i=0;i<20;i++)
        {
        printf("%d. %d \n",i,arr[i]);
        }



}

这是输出:

  1. 10
  2. 1
  3. 6
  4. 2
  5. 13
  6. 19
  7. 2
  8. 19
  9. 4
  10. 19
  11. 14
  12. 18
  13. 12
  14. 2
  15. 17
  16. 15
  17. 0
  18. 1
  19. 18
  20. 8

提前致谢:D

【问题讨论】:

  • 问题是什么?
  • 考虑从一个包含 0 到 19 整数的数组开始,并使用 Fisher-Yates shuffle 算法,而不是通过生成具有先前元素中不存在的值的每个元素来构建数组。 .
  • 正如@Thomas 所说,如果你想在 0 到 19 范围内的数字没有重复,那么从这些数字开始并随机播放。
  • 刚刚编辑了问题以更正一些拼写错误(例如标题中的错误 "differen" 而不是正确的 "differenT")。

标签: c++ random shuffle


【解决方案1】:
#include <vector>
#include <algorithm>
...
vector<int> vec;
for (int i=0; i < 20; ++i) vec.push_back(i);

random_shuffle(vec.begin(), vec.end());

【讨论】:

  • 不重新实现轮子很好,但std::random_shuffle 不是那么好 - 如果你可以使用 C++11,你应该强烈喜欢 std::shuffle 取而代之。 std::random_shuffle 仍然允许在内部基于rand()(出于兼容性原因,通常仍然如此),这意味着它继承了各种令人兴奋和微妙的缺陷。 @Stephan T. Lavavej 在今年的 Going Native 会议上发表了精彩的演讲,其中包括对此的一些讨论(见 23:30 左右):channel9.msdn.com/Events/GoingNative/2013/…
  • @DanBjorge 尽管我喜欢这种方法,但对于以前没有使用过它们的人来说,有很多东西可能看起来太神奇了。另一方面,random_shuffle 的实现非常简洁明了。
【解决方案2】:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main(){
    int arr[20];
    srand(time(NULL));
    int temp;

    temp=rand()%20;

    int x=0;

    while(x<20)
    {
          if(x==0)
          {
              arr[x]=temp;
              x++;
          }
          else
          {
              int j;
              do
              {
                  temp=rand()%20;
                  for(j=0;j<x;j++)
                  {
                      if ( temp==arr[j] ) break;
                  }
              } while ( j < x );
              arr[x]=temp;
              x++;
           }
     }

     for(int i=0;i<20;i++)
       {
       printf("%d. %d \n",i,arr[i]);
       }

}

【讨论】:

    【解决方案3】:

    想想你的循环

    for(int j=1;j<=x;j++)
    {
         do
         {
              temp=rand()%20;  
         }while(temp==arr[x-j]);
    }
    

    以x=8时的位置为例。这将循环 j=1 到 j=7。它将继续生成一个数字,直到它与正在检查数组的当前数字不同,直到到达数组的开头。但是,请考虑何时达到 j=7。当生成一个新数字时,它可能与数组中的第一个元素不同,因此将退出 do-while 循环;但是,它可能仍然与您数组中的其他数字相同?

    您需要(对于每个元素):生成一个随机数。检查它与数组中的任何数字都不匹配。如果确实重新开始,如果不设置数组号继续。

    【讨论】:

      【解决方案4】:

      您可以准备一个std::vector,在您想要的范围内存储唯一的数字,然后使用std::shuffle() 对其进行随机播放。

      请注意rand() is considered harmful,因此您可能希望使用更好的伪随机数生成器,例如 Marsenne Twister 引擎std::mt19937

      可编译的注释代码如下:

      #include <algorithm>    // for std::shuffle
      #include <iostream>     // for std::cout
      #include <random>       // for std::mt19937, std::random_device
      #include <vector>       // for std::vector
      using namespace std;
      
      vector<int> PrepareUniqueRandomNumbers(const int count) 
      {
          // Prepare the vector with unique numbers 0,1,2,...,(count-1)
          vector<int> numbers;
          numbers.reserve(count);
          for (int i = 0; i < count; ++i)
              numbers.push_back(i);    
      
          // Use Mersenne Twister engine as pseudo-random number generator
          random_device rd;
          mt19937 prng(rd());
      
          // Shuffle the vector, so the numbers
          // appear in a (pseudo-)random order.
          shuffle(numbers.begin(), numbers.end(), prng); 
      
          return numbers;
      }
      
      int main() 
      {
          const auto numbers = PrepareUniqueRandomNumbers(20);
          for (auto x : numbers)
              cout << x << '\n';     
      }
      

      【讨论】:

        【解决方案5】:

        如果您已经知道将只存储 20 个数字,则无需使用向量。 rand() 函数已经过时并且不是很好的 C++ 风格。您也不需要 Mersenne-Twister 作为您的意图的引擎,这绝对没有必要。

        #include <array>
        #include <random>
        #include <algorithm>
        
        int main()
        {
            std::array<int, 20> randomNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
            std::random_device randomDevice;
            std::default_random_engine engine(randomDevice());
            std::shuffle(randomNumbers.begin(), randomNumbers.end(), engine);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-24
          • 2020-12-28
          • 2012-10-06
          相关资源
          最近更新 更多