C++ 如何确保rand生成的0到1之间的随机数不是0?
我正在模拟一个排队模型,我需要用这个算法生成我的到达量。然而,我有时会得到0.000000作为随机值R1,并且不可能计算ln(0),因此过程停止。我如何避免得到0 我曾考虑将0.0000001添加到其中,但这不是很糟糕,因为我可能会得到大于1的值吗C++ 如何确保rand生成的0到1之间的随机数不是0?,c++,random,C++,Random,我正在模拟一个排队模型,我需要用这个算法生成我的到达量。然而,我有时会得到0.000000作为随机值R1,并且不可能计算ln(0),因此过程停止。我如何避免得到0 我曾考虑将0.0000001添加到其中,但这不是很糟糕,因为我可能会得到大于1的值吗 #include<stdio.h> #include<conio.h> #include<math.h> #include<stdlib.h> #include<time.h> main(
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
main()
{
int a=3, b=4, T=500, I=0, l=1504;
srand(time(NULL));
float R1, R2, t=0, S[10000], f;
printf("Utilizaremos la funcion at+b para el simular el poceso\n");
while(t<T){
R1=rand()/(double)RAND_MAX;
t= t-log(R1)/l;
R2=rand()/(double)RAND_MAX;
f = a*t+b;
if(R2<f/l){
I=I+1;
S[I]=t;
printf(" \n I %d, R1 %f, R2 %f, t %f, S[i] %f", I,R1,R2,t,S[I]);
}
}
getche();
return 0;
}
#包括
#包括
#包括
#包括
#包括
main()
{
INTA=3,b=4,T=500,I=0,l=1504;
srand(时间(空));
浮点数R1,R2,t=0,S[10000],f;
printf(“在+b段模拟操作中的实用功能”);
虽然(t不是说rand()
是一件好事,但是有效地避免零很容易:
double nzrand() {
constexpr double max=RAND_MAX+1.;
return (rand()+1.)/max;
}
这可以精确返回1;当然,使用+2.
可以避免这一点
当然,更常见的方法是在[0,1]上生成随机值(这里,通过在分母上加1而不是分子),然后计算log(1-x)
只要得到一个随机数,直到得不到0为止
double myrand()
{
while(1)
{
double r = rand()/(double)RAND_MAX;
if (r != 0)
return r;
}
}
...
R1 = myrand(); // Will not be 0
我可以想出两个简单的方法
在[0,1]中生成一个数字,并从1中减去:
R1 = rand() / (RAND_MAX + 1.0);
R1 = 1.0 - R1;
将rand()的结果加1,并相应地增加除数:
R1 = (rand() + 1.0) / (RAND_MAX + 1.0);
<>这两个结果都是(0,1]、< P>中的一个新的更好的C++方法是使用C++ 11标准库< /P>的新方法。
使用,您可以将范围指定为double
值,如(1e-12,1.0)
。或者更好地使用(std::numeric_limits::min(),1.0)
,这将为您提供最小的double
值,该值尚未为零,但仍在标准化(2.122e-314
)
完整示例:
#include <stdio.h>
#include <math.h>
#include <random>
int main()
{
int a = 3, b = 4, T = 500, I = 0, l = 1504;
std::random_device rndsource;
std::minstd_rand rndgen(rndsource());
std::uniform_real_distribution<double> dist(1e-12, 1.0);
double R1, R2, t = 0, S[10000], f;
printf("Utilizaremos la funcion at+b para el simular el poceso\n");
while (t < T) {
R1 = dist(rndgen);
t = t - log(R1) / l;
R2 = dist(rndgen);
f = a * t + b;
if (R2 < f / l) {
I = I + 1;
S[I] = t;
printf(" I %d, R1 %f, R2 %f, t %f, S[i] %f\n", I, R1, R2, t, S[I]);
}
}
return 0;
}
#包括
#包括
#包括
int main()
{
INTA=3,b=4,T=500,I=0,l=1504;
std::随机_设备rndsource;
std::minstd_rand rndgen(rndsource());
标准:均匀真实分布区(1e-12,1.0);
双R1,R2,t=0,S[10000],f;
printf(“在+b段模拟操作中的实用功能”);
而(t
std::minstd_rand
是一种LCG,在大多数科学应用中非常快速且可用。为了更好地预测,请尝试使用std::mt19937
PRNG。好的,下面是正确的答案
- 首先,您应该使用C++11工具(或者,如果您使用的是C++03,则使用类似的BOOST随机库)
- 其次,默认的双随机数生成需要至少53个尾数随机位,因此最好使用64位比特流生成器(以下示例中为mt19937_64)。因此,对rng的一次调用将生成一个双随机数,并且在64位平台上通常会更快
- 第三,默认的统一双精度生成器生成严格[0…1]范围内的数字。使用1-R技巧将其推入(0…1)范围
- 第四,您的代码有一个bug-很容易溢出数组的大小并导致内存损坏,因此,我添加了适当的保护
- 最后-请不要像其他人建议的那样使用随机_设备。一般来说,您需要完全可重复的运行,所以最好控制种子
代码,Visual C++2019,Win10 x64
#include <cmath>
#include <random>
#include <cstdio>
int main() {
int a = 3, b = 4, T = 500, I = 0, l = 1504;
double R1, R2, t = 0, S[10000], f;
std::mt19937_64 rng{ 7719716254321ULL }; // init with known seed - reproducability
// no need in random device
std::uniform_real_distribution<double> rnd{};
printf("Utilizaremos la funcion at+b para el simular el poceso\n");
while (t < T) {
R1 = rnd(rng);
t = t - log(1.0 - R1) / l;
R2 = rnd(rng);
f = a * t + b;
if (R2 < f / l) {
S[I] = t;
printf(" I %d, R1 %f, R2 %f, t %f, S[i] %f\n", I, R1, R2, t, S[I]);
++I;
if (I == sizeof(S) / sizeof(S[0]))
break;
}
}
(void)getchar();
return 0;
}
#包括
#包括
#包括
int main(){
INTA=3,b=4,T=500,I=0,l=1504;
双R1,R2,t=0,S[10000],f;
std::mt19937_64 rng{7719716254321ULL};//具有已知种子复制能力的init
//无需在随机设备
一致实分布rnd{};
printf(“在+b段模拟操作中的实用功能”);
而(t
还有另一种可能性:
double increment = 0.000000001; // However small you need.
double near_zero = 0.005;
...
double nzrand() {
double nzr = rand()/(double)RAND_MAX;
if (nzr < near_zero) {
nzr += increment;
}
return nzr;
} // end nzrand()
double increment=0.000000001;//无论需要多小。
双近零=0.005;
...
双nzrand(){
双nzr=rand()/(双)rand_MAX;
如果(nzr<接近零){
nzr+=增量;
}
返回nzr;
}//end nzrand()
这只增加了一个小的增量,如果初始值短于1,它就永远不会超过一个,它永远不会返回零,最小可能的返回值是给定的增量。< /P>如果你得到0的随机数,又会怎样?在C++中你应该使用而不是<代码> RAND()/<代码>,如果这是C。(看起来是这样),请更新标签。兰德()被认为是有害的-斯蒂芬·T·拉瓦维,如果
rand()
可以返回INT\u MAX
,这可能会溢出。你应该将1.0
添加到rand()
而不是1
@Kevin:当然-我这样做是为了rand\u MAX
而不是rand()
本身。编辑。