文章目录
前言
通常想要使用随机数的时候,在网络上搜索,他们只会告诉你用srand播种。
而且是以秒为单位,这就有了个巨大的问题,而且这个问题在Windows系统中不算常见但是在Linux中的必出的问题。
通常网上的教程会教你这么写随机种子
srand((unsigned)time(NULL));
这样写没什么问题,但是如果你想执行一个非常快的语句,比如for循环,就会出现问题。
比如下面这段代码int arr[4096]; for(int x = 0; x < 4096; ++x) { arr[x] = rand(); }
此段代码在Windows中表示的可能不是特别明显,但在Linux中你就会发现输出的几乎都是同一个值。
为什么呢?因为它以秒为单位,而for循环执行的速度是非常快的。
代码
我们自己编写一个随机数种子播种函数,然后在需要使用随机数时调用一次它。
这个随机数种子是以纳秒为单位的,就完美避免了以秒为单位出现的更新不及时的情况。
#include <sys/timeb.h>
#include <time.h>
static void setRandomSeed()
{
clockid_t a = 0;
struct timespec p = {0, 0};
clock_gettime(a, &p);
srand((unsigned)p.tv_nsec);
}
此代码专门针对不同系统进行过改动,比如你可以将这段代码原封不动的从Windows移植到Linux中,执行不会出现任何问题。
2023-05-26 补充
通过这种方法获得的随机数都是伪随机数,不可能是真随机数。
如果你是使用srand函数做种子来生成用于加密算法密钥的随机数的话,那么我是非常非常非常不建议的,因为srand函数的范围只有0 ~ 232-1的范围,所以攻击者可以通过穷举等手段来获得所有可能的伪随机数从而得到可能的加密算法的密钥。
如果你是想生成真随机数,那么可以利用各种电子设备噪声,放射性衰变,周围环境音,一张图片或视频来得到真正的随机数。
或者使用对应的密码学安全随机数,这种库已经有非常多,此处不展开说明。