伪随机数
计算机是无法产生真正的随机数的,大部分程序和语言中的随机数(比如 C 中的,MATLAB 中的),都只是伪随机数。是由可确定的函数(常用线性同余),通过一个种子(常用时钟),产生的伪随机数。这意味着:如果知道了种子,或者已经产生的随机数,都可能获得接下来随机数序列的信息(可预测性)。
方法一
使用c++伪随机数生成器random
#include <random> // 详细信息见 cpp-reference 参考网站
using namespace std;
int main(){
random_device rd; // 将用于获得随机数引擎的种子
mt19937 gen(rd()); // 以 rd() 播种的标准
uniform_int_distribution<double> t(a, b); // 限定范围为[a,b)的整数
uniform_real_distribution<double> t(a, b); // 限定范围为[a,b)的浮点数
cout << t(gen) << endl;
return 0;
}
方法二
使用c语言库函数srand
#include <time.h>
int mian(){
srand(time(NULL));
cout << rand() << endl; // 默认生成[0, RAND_MAX]内的整数,RAND_MAX一般为2^16 / 2
cout << rand() * 1.0 / RAND_MAX * b + a << endl; // 生成 [a, b] 之间的浮点数
return 0;
}
计算定积分
$$
\int_{0}^{\pi}sin(x)dx
$$
基本思路:通过数值随机数,统计落在函数内部的点个个数,来逼近定积分的计算结果
不同语言效率对比:
C++
使用random
方法,耗时51s
C
使用rand
方法耗时9s
python
使用math.uniform
方法,耗时353s
详细代码
C or C++
注意事项:使用具有
uniform_real_distribution
函数的randT
函数获取随机数时,切记不要将获得随机数引擎的种子和播种规则和放入randT
函数内,由于randT
被不断的调用,实际上随机数种子也在不断的刷新,因此每次randT
得到的结果都会一致,所以我们需要将随机数引擎的种子和播种规则放在全局变量或者形参内。
#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <random>
#define PI acos(-1)
using namespace std;
double f(double x) {
return sin(x);
}
random_device rd; // 将用于获得随机数引擎的种子
mt19937 gen(rd()); // 以 rd() 播种的标准
double randT(double a, double b) {
uniform_real_distribution<double> res(a, b);
return res(gen);
}
double solve(int n) {
double cnt = 0;
for (long long i = 0; i < n; i++) {
// double x = 1.0 * rand() / RAND_MAX * (PI), y = 1.0 * rand() / RAND_MAX * (1.0);
double x = randT(0.0, PI), y = randT(0.0, 1.0);
if (y <= f(x))
cnt++;
}
return cnt / n * PI;
}
int main() {
system("chcp 65001");
clock_t start = clock();
for (long long i = 10; i < pow(10, 9); i *= 10) {
printf("第%d次迭代,结果是:%.6f\n", i, solve(i));
}
cout << (clock() - start) / CLOCKS_PER_SEC << "s" << endl;
system("pause");
return 0;
}
python
import math
import random
from sympy import *
import time
def f(x):
return math.sin(x)
def solve(n):
cnt = 0
for i in range(n):
x, y = random.uniform(0, math.pi), random.uniform(0, 1)
if y <= f(x):
cnt = cnt+1
return cnt / n * math.pi
time_start = time.time()
for i in range(int(math.pow(10, 9))):
print("第%d次迭代, 结果为:%f" %(i, solve(i)))
i *= 10
time_end = time.time()
print(time_end - time_start)
x = symbols("x") # python库实现的定积分计算, 对比结果
print(integrate(sin(x), (x, 0, math.pi)))