有一次,我的老师教我在 C++ Builder 中使用randomize()
和random()
函数生成伪随机数。现在我更喜欢在 VS 2012 中工作,但是当我尝试在那里使用这些功能时,它说“找不到标识符”,即使我添加了#include <stdlib.h>
. 经过一段时间的谷歌搜索,我发现还有rand()
和srand()
功能。它们之间有什么区别,哪个更好用?
7 回答
randomize()
并且random()
不是标准库的一部分。也许您的老师使用这些名称编写了函数供您在课堂上使用,或者您的意思是random()
它们srandom()
是 POSIX 的一部分,在 Windows 上不可用。rand()
并且srand()
是标准库的一部分,将由任何符合标准的 C++ 实现提供。
您应该避免使用新rand()
的srand()
C++11<random>
库。<random>
被添加为 C++11 标准的一部分(VS2012 确实提供了它)。
解释原因的视频:rand()
被认为是有害的
rand()
通常是低质量的 pRNG,不适合需要合理水平的不可预测性的应用程序。<random>
提供多种具有不同特性的引擎,适用于许多不同的用例。将结果
rand()
转换为您可以直接使用的数字通常依赖于难以阅读且容易出错的代码,而使用<random>
分布很容易并产生可读的代码。在给定分布中生成值的常用方法
rand()
进一步降低了生成数据的质量。%
通常会使数据产生偏差,浮点除法仍然会产生非均匀分布。<random>
发行版质量更高,可读性更强。rand()
依赖于隐藏的全局资源。除其他问题外,这会导致rand()
线程不安全。一些实现会保证线程安全,但这不是必需的标准。由 pRNG提供的引擎<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()不好而random()不是,但事实证明您的里程可能会有所不同。这是 gcc 对“有什么区别......”问题的答案,由 stdlib.h 的 gcc 版本提供(强调添加):
/* 这些是实际做事的函数。srandom random',
',
initstate' and
setstate' 函数来自 BSD Unices。rand' and
ANSI 标准需要 srand 函数
。我们为同一个随机数生成器提供两个接口。 //返回一个介于0和RAND_MAX之间的随机长整数。*/
函数rand()
和random()
至少从 POSIX.1-2001 开始由 POSIX 定义(并且randomize()
未标准化)。
在较旧的rand()
实现中,以及在不同系统上的当前实现中,低阶位的随机性远低于高阶位。
如果可用,random()
则不会遇到此问题。
此外,现代版本rand()
使用与random()
. 所以rand()
可能是正确的,但不能保证。
因此,始终使用random()
而不是rand()
. 如果random()
在您的操作系统上不可用,请要求操作系统开发人员提供更新的标准 API 实现(2001 标准现在已经足够老,可以期望任何系统都提供它)。
看起来您使用的是 C 风格的函数,即使您的问题被标记为 C++。此外,stdlib.h
它是 C 标准库的头文件。random()
C 标准库中没有这样的函数randomize()
。C 标准库具有rand()
和srand()
.
如果你正在使用random()
或类似的东西stdlib.h
,它一定是 Borland 编译器包中的一些非标准库扩展。
所以,如果你想坚持 C 风格的标准函数,那就是,再一次,rand()
和srand()
. 但是,如果您使用 C++ 编写,您可能在 C++ 标准库中有更好(和更合适)的选项。
srand()
是用于播种(伪)随机数生成器的 C 标准库实现。 rand()
是 C 标准库中的(伪)随机数生成器。
C++ 在<random>
头文件中实现了一个更新的(伪)随机数生成器,它有多种不同的引擎可供使用: http ://en.cppreference.com/w/cpp/numeric/random
我不熟悉,randomize()
但random()
它们不是标准库的一部分。你应该避免使用rand()
这个视频解释了为什么使用 rand() 被认为是有害的。
您应该使用C++11中引入的随机标头,这是同时使用std::uniform_real_distribution和std::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 ;
}
这是使用 c++ 之外的随机数形式的解决方法。
这是 C 语言的原始程序,从“ http://www.programmingsimplified.com/ ”复制而来。该程序无法运行,因为“temp1 = 1 + random (588);” “temp2 = 1 + 随机(380);” 语句不起作用。'random' 不是 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 秒,然后终止。