C/C++生成随机数
目录
随机数的用途
- 单元测试
- 游戏抽奖
- 仿真及安全
- and so on
伪随机数:c++产生随机数
生成器(engine):能够产生离散的等可能分布数值
- 如线性同余法(linear_congruential_engine)
- 梅森旋转法(meraenne_twister_engine)
- 滞后Fibonacci(substract_with_carry_engine)
分布器(distribution):能够把generator均匀分布值映射到其他常见分布
- 如均匀分布(unifor)
- uniform_int_distribution 整数均匀分布
- uniform_real_distribution 浮点数均匀分布
- 正态分布(normal) (仅有yes/no两种结果,概率一个p,一个1-p)
- 二项分布(binorial)
- 泊松分布(poisson)
#include <random>
default_random_engine e{}; // default engine
// distribution将产生的随机数映射到整数1..6
uniform_int_distribution<int> one_to_six{1, 6};
// 产生一个符合指定规则的随机数
#include <random>
int x = u(e);
auto dice{bind(u, e)};
int y = dice();
#include <random>
// 产生随机数
int rand_int(int low, int high)
{
using namespace std;
static default_random_engine e;
using Dist = uniform_int_distribution<int>;
static Dist u{};
return u(e, Dist::param_type{low, high});
}
#include <random>
#include <iostream>
std::mt19937 gen;
void test_random(){
std::uniform_real_distribution<> d(4.5, 5.2);
for (int i = 0; i < 20; ++i)
std::cout << d(gen) << std::endl;
getchar();
}
int main(int argc, char **argv){
return test_random();
}
// output
4.59483
5.08451
5.17821
4.65472
4.71572
4.88305
4.63187
5.19502
5.19752
5.17739
5.00809
5.18678
4.5769
5.05867
4.70792
4.50335
4.57873
4.94783
5.1149
4.85256
伪随机数:C语言实现随机数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/*
// Maximum value that can be returned by the rand function:
#define RAND_MAX 0x7fff
_ACRTIMP void __cdecl srand(_In_ unsigned int _Seed);
_Check_return_ _ACRTIMP int __cdecl rand(void);
*/
void show() {
printf("rand()------------\n");
for (int i = 0; i < 10; ++i)
printf("%d |", rand());
printf("\n");
}
void show_range(int a, int b) { // 固定范围的随机数
for (int i = 0; i < 10; ++i)
printf("%d |", rand() % (b - a) + a);
printf("\n");
}
void func() {
printf("-------test start------------\n");
show(); /*rand() == rand(1)*/
printf("-------srand(1)--------------\n");
srand(1);
show();
printf("-------srand(11111)----------\n");
srand(11111);
show();
printf("-------srand(time(NULl))-----\n");
srand(time(NULL));
show();
printf("-------test end--------------\n");
return;
}
-------test start------------
rand()------------
41 |18467 |6334 |26500 |19169 |15724 |11478 |29358 |26962 |24464 |
-------srand(1)--------------
rand()------------
41 |18467 |6334 |26500 |19169 |15724 |11478 |29358 |26962 |24464 |
-------srand(11111)----------
rand()------------
3554 |26670 |1503 |15804 |24395 |27484 |20568 |13190 |2698 |7943 |
-------srand(time(NULl))-----
rand()------------
16547 |21195 |9007 |7453 |12018 |30665 |27311 |4207 |12232 |15391 |
-------test end--------------
-
rand函数产生随机数(收获果实)
int rand();
头文件为<stdlib.h>
-
srand设置随机数种子(播种种子)
void srand( unsigned seed );
-
不设置种子值时,默认种子为1,即
srand(1)
-
为保证每个 程序每次产生的随机数不同,使用前可以参考使用时间作为种子
srand(time(NULL))
添加头文件<time.h>
-
rand不是线程安全的函数(原则是每个线程的种子不一致)
- posix的替代方案时
rand_r(int *seed)
- 可以使用线程id作为种子来处理
- posix的替代方案时
真随机数数
C语言中rand()函数生成的数实际上是一个伪随机序列,这意味着每次程序运行时,得到的序列是预先确定好的,因此并不能真正满足安全性要求。
C++标准库中的随机数生成器(
PRNG是一种基于确定性算法的随机数生成器,它通过一个起始种子(或者称为随机种子)生成一个序列,看起来是随机的。然而,这个序列实际上是根据算法计算得出的,因此在给定相同的种子的情况下,生成的随机数序列将是可预测的。
在C++标准库中,std::rand()函数和相关的随机数生成器类(如std::default_random_engine)都是基于PRNG的。它们提供的随机数序列具有良好的统计特性,但不适合用于需要高度安全性的场景,如密码学或加密算法。
如果你需要生成真正的随机数,可以使用操作系统提供的随机数生成器。
- 在Linux和Unix系统中,可以使用/dev/random或/dev/urandom设备来获取真随机数。
- 在Windows系统中,可以使用CryptGenRandom()函数。这些方法利用了操作系统的硬件和环境熵池来生成真正的随机数。
- 使用第三方库,如Crypto++或Botan,它们提供了更安全和真随机的随机数生成功能
使用/dev/urandom
生成真随机数
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* urandom = fopen("/dev/urandom", "r");
if (urandom == NULL) {
printf("无法打开 /dev/urandom 设备\n");
return 1;
}
unsigned int random_number;
fread(&random_number, sizeof(random_number), 1, urandom);
printf("生成的随机数:%u\n", random_number);
fclose(urandom);
return 0;
}
使用CryptGenRandom
生成真随机数
#include <iostream>
#include <Windows.h>
#include <wincrypt.h>
int main() {
HCRYPTPROV hCryptProv;
BYTE randomBytes[4];
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
std::cerr << "无法获取加密服务提供者句柄" << std::endl;
return 1;
}
if (!CryptGenRandom(hCryptProv, sizeof(randomBytes), randomBytes)) {
std::cerr << "无法生成随机数" << std::endl;
CryptReleaseContext(hCryptProv, 0);
return 1;
}
// 将随机数打印到控制台
for (int i = 0; i < sizeof(randomBytes); ++i) {
printf("%02x ", randomBytes[i]);
}
std::cout << std::endl;
CryptReleaseContext(hCryptProv, 0);
return 0;
}
本文来自博客园,作者:flxx,转载请注明原文链接:https://www.cnblogs.com/faithlocus/p/15506903.html