基于正态分布指定范围内的随机数生成算法

1、需求背景

生成一个范围(n到m,例如100到150)的随机数,但不是纯粹随机(均匀分布)的,想要的结果是基于正态分布。另外想要数字“聚集”在125左右。

生成符合正太分布的随机数不难,但是如何达到我所要求的范围?

2、分析与代码

标准正态分布的平均值为0,标准差为1;如果要使用均值m和偏差进行分布s,只需乘以s,然后加m。由于理论上的正态分布是无限的,因此如果不明确拒绝超出范围的数字,就无法对范围(例如100到150)进行硬性限制,但是可以通过适当选择偏差来确保(例如)您的数字的99%将在此范围内。

大约99.7%的总数处于+/- 3个标准差之内(3σ),因此,如果您选择的是大约(25/3 == 3σ),则它应能正常工作。

所以你想要像这样的东西: (normal * 8.333) + 125  (标准正态分布变换到正态分布)

import numpy as np
import matplotlib.pyplot as plt
from math import sqrt

# # bi = np.random.binomial(n=100, p=0.5, size=200)
# n = np.random.normal(100*0.5, sqrt(100*0.5*0.5), size=500)
# #
# # plt.hist(bi, bins=20, normed=True);
# plt.hist(n, alpha=0.5, bins=20, normed=True);
# plt.show();
# print()

from scipy.stats import truncnorm

def get_truncated_normal(mean=0, sd=1, low=0, upp=10):
    return truncnorm(
        (low - mean) / sd, (upp - mean) / sd, loc=mean, scale=sd)

X1 = get_truncated_normal(mean=2, sd=1, low=1, upp=10)
X2 = get_truncated_normal(mean=5.5, sd=1, low=1, upp=10)
X3 = get_truncated_normal(mean=5000, sd=1000, low=1000, upp=10000)

import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, sharex=True)
ax[0].hist(X1.rvs(10000), normed=True)
ax[1].hist(X2.rvs(10000), normed=True)

_ = X3.rvs(100000)
ax[2].hist(_, normed=True)
plt.show()

np.savetxt("result.txt", [int(j) for j in _], fmt='%d');

3、数据验证

Refer:

[1] How to get a normal distribution within a range in numpy?

https://stackoverflow.com/questions/36894191/how-to-get-a-normal-distribution-within-a-range-in-numpy

[2] How to generate a random normal distribution of integers

https://stackoverflow.com/questions/37411633/how-to-generate-a-random-normal-distribution-of-integers

[3] Random number within a range based on a normal distribution

https://stackoverflow.com/questions/2751938/random-number-within-a-range-based-on-a-normal-distribution

[4] python模拟常用分布

https://blog.csdn.net/howhigh/article/details/78007317

 

转自:https://my.oschina.net/leejun2005/blog/76984

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用C语言中的标准库函数来生成正态分布随机数。具体步骤如下: 1. 包含头文件:`#include <stdio.h>` 和 `#include <stdlib.h>`。 2. 使用 `rand()` 函数生成一个介于0和 `RAND_MAX` 之间的随机数。 3. 将该随机数归一化到范围 [0, 1] 内,即除以 `RAND_MAX`。 4. 使用 Box-Muller 转换将归一化的随机数转换为正态分布随机数。 下面是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> double generateNormalDistribution(double mean, double stddev) { double u = (double)rand() / RAND_MAX; // 归一化到 [0, 1] double v = (double)rand() / RAND_MAX; // 归一化到 [0, 1] double z = sqrt(-2.0 * log(u)) * cos(2.0 * M_PI * v); // 使用 Box-Muller 转换 return mean + stddev * z; } int main() { double mean = 0.0; // 正态分布的均值 double stddev = 1.0; // 正态分布的标准差 srand(time(NULL)); // 初始化随机数种子 for (int i = 0; i < 10; i++) { double randomNum = generateNormalDistribution(mean, stddev); printf("%f\n", randomNum); } return 0; } ``` 在上面的示例代码中,`generateNormalDistribution()` 函数接受正态分布的均值和标准差作为参数,并返回一个正态分布随机数。`main()` 函数中的循环生成并打印了10个正态分布随机数。 请注意,这只是一个简单的示例代码,生成的随机数可能不够精确。如果需要更精确的结果,可以考虑使用更复杂的随机数生成算法或者使用专门的数值计算库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值