【问题标题】:What difference between rand() and random() functions?rand() 和 random() 函数有什么区别?
【发布时间】:2013-09-14 14:05:28
【问题描述】:

有一次,我的老师教我在 C++ Builder 中使用 randomize()random() 函数生成伪随机数。现在我更喜欢在 VS 2012 中工作,但是当我尝试在那里使用这些功能时,它说“找不到标识符”,即使我添加了 #include <stdlib.h>。经过一段时间的谷歌搜索,我发现还有rand()srand() 函数。它们之间有什么区别,哪个更好用?

【问题讨论】:

  • 你应该使用random header,尤其是因为using rand() is considered harmful
  • “认为有害”是一种主观衡量标准。这取决于你在做什么。毕竟它只是一个伪随机生成器。
  • 这是一个非常糟糕的结果,并且无法证明分布的任何属性(如果您首先生成随机数,这可能很重要。)

标签: c++ random


【解决方案1】:

看起来您使用的是 C 风格的函数,即使您的问题被标记为 C++。此外,stdlib.h 是来自 C 标准库的头文件。 C标准库中没有random()randomize()这样的函数。 C 标准库有rand()srand()

如果你通过stdlib.h使用random()或类似的东西,它一定是Borland编译器包中的一些非标准库扩展。

所以,如果你想坚持使用 C 风格的标准函数,那又是 rand()srand()。但是,如果您使用 C++ 编写,您可能在 C++ 标准库中有更好(和更合适)的选项。

【讨论】:

  • 是不是说random()和randomize()只包含在C++ Borland编译器中?
  • @Sunrise:这就是非标准的意思,是的。
【解决方案2】:

randomize()random() 不是标准库的一部分。也许您的老师使用这些名称编写了用于您的课堂的函数,或者您的意思是 random()srandom(),它们是 POSIX 的一部分,在 Windows 上不可用。 rand()srand() 是标准库的一部分,将由任何符合标准的 C++ 实现提供。


您应该避免使用 rand()srand(),并使用新的 C++11 <random> 库。 <random> 是作为 C++11 标准的一部分添加的(VS2012 确实提供了它)。

解释原因的视频:rand() Considered Harmful

  • rand() 通常是低质量的 pRNG,不适合需要合理水平的不可预测性的应用程序。 <random> 提供了多种具有不同特性的引擎,适用于许多不同的用例。

  • rand() 的结果转换为您可以直接使用的数字通常依赖于难以阅读且容易出错的代码,而使用<random> 分发版很容易并且可以生成可读的代码。

  • 使用rand() 在给定分布中生成值的常用方法进一步降低了生成数据的质量。 % 通常会使数据产生偏差,浮点除法仍然会产生非均匀分布。 <random> 发行版质量更高,可读性更强。

  • rand() 依赖于隐藏的全局资源。除其他问题外,这会导致 rand() 不是线程安全的。一些实现会保证线程安全,但这不是必需的标准。 <random> 提供的引擎将 pRNG 状态封装为具有值语义的对象,从而可以灵活控制状态。

  • srand() 只允许有限范围的种子。 <random> 中的引擎可以使用允许最大可能种子数据的种子序列进行初始化。 seed_seq 还实现了一个常见的 pRNG 预热。


<random>使用示例:

#include <iostream>
#include <random>

int main() {
  // create source of randomness, and initialize it with non-deterministic seed
  std::random_device r;
  std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
  std::mt19937 eng{seed};

  // a distribution that takes randomness and produces values in specified range
  std::uniform_int_distribution<> dist(1,6);

  for (int i=0; i<100; ++i) {
    std::cout << dist(eng) << '\n';
  }
}

【讨论】:

  • 所有事情都是相对的,取决于你在做什么,rand() 可能就足够了。 (还有,为什么所有这些演示文稿都是视频?C++主要是专业使用的,这意味着我们无法激活机器上的声音,也无法观看视频。)
  • @JamesKanze 耳机在办公室很方便。可能也有不错的文本资源,但我不知道任何手头。即使质量和不均匀性不是问题,人们仍然应该更喜欢&lt;random&gt;,只是为了便于阅读。
  • @AndreyT 在没有&lt;random&gt; 可用但应该首选rand() 的情况下。而且你说没有人认为rand() 有害是不正确的。 rand() 太有利于错误使用(不仅在质量方面,而且还造成数据竞争),并且与替代品相比没有任何好处。
  • @JamesKanze “我没有完全意识到其中的任何内容”而且我也没有意识到任何内容。我想一旦有人知道某事,我们应该烧掉该信息的所有副本并且永远不要提及它? “大多数人还不能使用 C++11”可能是大多数人使用 C++11,但这通常不是因为 C++11 不适用于他们的平台。应鼓励程序员、经理等转向 C++11。其中一部分是展示它是如何变得更好的。
  • @JamesKanze “它在生产代码中不可用,除非在特殊情况下” 就像我说的,在任何情况下&lt;random&gt; 都不可用,但应该首选rand()。我还认为“例外”是对其可用性的低估。 “但它是最简单的解决方案”如果“更简单”的意思与那些说 C 应该优先于 C++ 的人的意思相同,因为它“更简单”。在最直接地表达程序的含义方面,我发现&lt;random&gt; 更简单。从rand() 中获得相同级别的抽象意味着自己实现它。
【解决方案3】:

srand() 是用于播种(伪)随机数生成器的 C 标准库实现。 rand() 是 C 标准库中的(伪)随机数生成器。

C++ 在&lt;random&gt; 头文件中实现了一个更新的(伪)随机数生成器,它有多种不同的引擎可供使用:http://en.cppreference.com/w/cpp/numeric/random

【讨论】:

    【解决方案4】:

    我不熟悉randomize()random(),但它们不是标准库的一部分。你应该避免使用rand() 这个视频解释了为什么using rand() is considered harmful

    你应该使用C++11中引入的random header,这里是同时使用std::uniform_real_distributionstd::uniform_int_distribution的例子:

    #include <iostream>
    #include <random>
    
    int main()
    {
        std::random_device rd;
    
        std::mt19937 e2(rd());
    
        std::uniform_int_distribution<> dist(1, 6);
        std::uniform_real_distribution<> distReal(1, 6);
    
        for( int i = 0 ; i < 10; ++i )
        {
           std::cout << dist(e2) << ",";
        }
        std::cout << std::endl ;
    
        for( int i = 0 ; i < 10; ++i )
        {
           std::cout << distReal(e2) << ",";
        }
        std::cout << std::endl ;
    
        return 0 ;
    }
    

    【讨论】:

      【解决方案5】:

      尽管(显然,上面)有人会以宗教热情断言 rand() 是坏的,而 random() 不是,但事实证明,您的里程可能会有所不同。这是 gcc 对“有什么区别......”问题的答案,由 stdlib.h 的 gcc 版本提供(强调添加):

      /* 这些是实际做事的函数。 random',srandom', initstate' andsetstate' 函数来自 BSD Unices。 ANSI 标准需要rand' andsrand' 函数。 我们为同一个随机数生成器提供两个接口。 / / 返回一个介于 0 和 RAND_MAX 之间的随机长整数。 */

      【讨论】:

        【解决方案6】:

        这是一种在 c++ 之外使用随机数形式的解决方法。

        这是 C 语言的原始程序,从“http://www.programmingsimplified.com/”复制而来 该程序无法运行,因为“temp1 = 1 + random (588);” “temp2 = 1 + 随机(380);” 语句不起作用。 “随机”不是 graphics.h、conio.h 或 stdlib.h 的函数 如果包含 random.h,它也不起作用。 此清单下方是随机函数的解决方法。

        #include<graphics.h>
        #include<conio.h>
        #include<stdlib.h>
        main()
        {
           int gd = DETECT, gm, area, temp1, temp2, left = 25, top = 75;
           void *p;
           initgraph(&gd,&gm,"C:\\TC\\BGI");
        
           setcolor(YELLOW);
           circle(50,100,25);
           setfillstyle(SOLID_FILL,YELLOW);
           floodfill(50,100,YELLOW);
        
           setcolor(BLACK);
           setfillstyle(SOLID_FILL,BLACK);
           fillellipse(44,85,2,6);
           fillellipse(56,85,2,6);
        
           ellipse(50,100,205,335,20,9);
           ellipse(50,100,205,335,20,10);
           ellipse(50,100,205,335,20,11);
        
           area = imagesize(left, top, left + 50, top + 50);
           p = malloc(area);
        
           setcolor(WHITE);
           settextstyle(SANS_SERIF_FONT,HORIZ_DIR,2);
           outtextxy(155,451,"Smiling Face Animation");
        
           setcolor(BLUE);
           rectangle(0,0,639,449);
        
           while(!kbhit())
           {
              temp1 = 1 + random ( 588 );
              temp2 = 1 + random ( 380 );
        
              getimage(left, top, left + 50, top + 50, p);
              putimage(left, top, p, XOR_PUT);
              putimage(temp1 , temp2, p, XOR_PUT);
              delay(100);
              left = temp1;
              top = temp2;
           }
        
           getch();
           closegraph();
           return 0;
        }
        

        随机数是用一个简单的 MS Excel 宏生成的,这里列出:

        Sub Macro1()
        Dim i
        For i = 1 To 400
        Randomize
        
        Range("a" & i) = Int(Rnd * 588) + 1
        Range("b" & i) = Int(Rnd * 380) + 1
        
        Next i
        End Sub
        

        这会生成 2 列随机数。每一列都被复制并粘贴到 它自己的 *.txt 文件,即 rnd1.txt 和 rnd2.txt 并放置在可以放置它们的目录中 由后面的 c++ 程序访问。 用正确的路径替换“c:\PATH\rnd1.txt”和“C:\PATH\rnd2.txt”。

        #include<iostream>
        #include<fstream> 
        #include<graphics.h>
        
        using namespace std;
         int i,j,k;
        int main(int argc, char** argv) {
           std::ifstream infile1;
           infile1.open("c:\\PATH\\rnd1.txt",ios::in);
           ifstream infile2;
           infile2.open("c:\\PATH\\rnd2.txt",ios::in);
           int gd = DETECT, gm, area, temp1, temp2, left = 25, top = 75;
           void *p;
           initgraph(&gd,&gm,"C:\\TC\\BGI");
        
           setcolor(YELLOW);
           circle(50,100,25);
           setfillstyle(SOLID_FILL,YELLOW);
           floodfill(50,100,YELLOW);
        
           setcolor(BLACK);
           setfillstyle(SOLID_FILL,BLACK);
           fillellipse(44,85,2,6);
           fillellipse(56,85,2,6);
        
           ellipse(50,100,205,335,20,9);
           ellipse(50,100,205,335,20,10);
           ellipse(50,100,205,335,20,11);
        
           area = imagesize(left, top, left + 50, top + 50);
           p = malloc(area);
        
           setcolor(WHITE);
           settextstyle(SANS_SERIF_FONT,HORIZ_DIR,2);
           outtextxy(155,451,"Smiling Face Animation ");
        
           setcolor(BLUE);
           rectangle(0,0,639,449);
        
           while(!kbhit())
           {
              infile1 >> j;
              temp1 = j;
              infile2 >> k;
              temp2 = k;
              if(infile2.eof()) {
               closegraph();
               void close();
               return 0;
                }                
              getimage(left, top, left + 50, top + 50, p);
              putimage(left, top, p, XOR_PUT);
              putimage(temp1 , temp2, p, XOR_PUT);
              delay(100);
              left = temp1;
              top = temp2;
              }
        
              }
        

        此程序将运行大约 40 秒,然后终止。

        【讨论】:

        • 使用 Excel 为 C++ 应用程序生成随机数... bleh。如果您不想使用“内置”选项,最好找到一个像样的库。 obligitory xkcd link
        • graphics.h、conio.h 和... EXEL?认真的吗?
        【解决方案7】:

        函数rand()random() 由POSIX 定义,因为至少是POSIX.1-2001(并且randomize() 不是标准化的)。

        在较早的rand() 实现上,以及在不同系统上的当前实现上,低位位的随机性远低于高位位。

        如果可用,random() 不会遇到此问题。

        此外,rand() 的现代版本使用与random() 相同的随机数生成器。所以rand() 可能是正确的,但不能保证。

        因此,请始终使用random() 而不是rand()。如果random() 在您的操作系统上不可用,请要求操作系统开发人员提供更新的标准 API 实现(2001 标准现在已经足够老,任何系统都可以提供它)。

        【讨论】:

          猜你喜欢
          • 2018-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-25
          • 2014-10-28
          • 2020-11-27
          • 2021-10-24
          相关资源
          最近更新 更多