Windows下的random_device
缘起
整个事情的起因是这样的:
C++第四个实验要生成一组随机序列数,众所周知,rand()
函数用的线性同余法生成随机数,但是这个随机数实际上是一个伪随机数。然后我就想用std::random_device
来生成真随机数。然而在Windows下,GCC的表现却让我大跌眼镜。编译环境是MinGW gcc5.3.0。
不同的表现
首先是示例代码:
|
|
GCC的情况
代码本身含义再清晰不过,在Linux下跑出了满意的结果。但是在Windows下居然跑出来这种结果:
|
|
是随机数没错啊。然而我们再跑一遍:
|
|
???
我就很懵,这东西是不是在Windows下没用的???
MSVC的情况
然后我又用Visual Studio 2015跑了一遍。这是第一次的结果:
|
|
这是第二次:
|
|
???
实现
本着无聊的原则,让我们看一下头文件:
没有什么头文件
实现都在.o
里面的,我什么都没找到。
然后查阅了Stack overflow,看到如下问题:
我跟着文章在cppreference看到这么一段话:
std::random_device
may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. In this case eachstd::random_device
object may generate the same number sequence.
那么实际上很明显了,windows下的GCC并没有完整实现std::random_device
,所以才会出现多次随机序列一样的情况。(我猜就是直接 proxy 到rand()
,种子都不换的)
那么MSVC呢?
http://stackoverflow.com/questions/9549357/the-implementation-of-random-device-in-vs2010
这里讲的很详细了,MSVC利用了很多数据来计算熵,然后使用RtlGenRandom()/SystemFunction036()
来计算随机数,可以认为是真随机。
同时,在Linux下,GCC使用读取/dev/urandom
的方式实现了std::random_device
,这个文件本身就是一个真随机数(实际上,还是伪随机,想了解更多点这个)生成器,也就很完美的实现了。
结论
其实结论到现在就很简单了,如果你要在Windows下编译C程序,请首选MSVC编译器,微软投了这么多人力物力不是白做的。
如果你不想装Visual Studio这么大的IDE,你可以选择Code::Blocks,它可以选择使用MSVC作为编译环境,具体怎么搭独立的MSVC编译环境请使用搜索引擎;你还可以使用Visual Studio Code,这个是微软家做的文本编辑器,不得不说是真的无敌,自带了一份MSVC编译环境,小东西用它写足够了。
Linux下请选择Clang或者GCC(个人强烈推荐Clang,之后会写文章说为什么)。
Windows下真的推荐不要再使用MinGW或者Cygwin了,GCC本身诞生就不是给Windows写的,很多东西支持上不如MSVC。
以上都不要信,喜欢用啥就用啥。
反正我是换成MSVC了。
P.S. 写的好水啊,怎么能写出这么水的文章的,还是需要学习一波