Wenping(Wendy)Zhang points out
SAS RAND
function“基本上给出了”标准“分发”。
作者描述了一个有趣的SAS %rndnmb
宏来从“非标准”发行版生成数据。不幸的是,代码不可用。所以,我敢于自己做。
如果我理解正确的维基百科says y 来自对数正态分布,如果
y = exp ^(mu + sigma * Z)。
以下公式连接非对数样本值的 mean 和 variance :
mu = ln((平均^ 2)/(sqrt(方差+平均值^ 2))
和
sigma = sqrt(ln(1 +(variance)/(mean ^ 2)))。
如果这是正确的,我的 y 将在日期时从对数正态分布中提取 Z来自标准正态分布Z,mu'= 0,sigma'= 1。
最后, y 来自对数正态分布 mean 和 variance 是否正确 y = exp ^(ln((平均^ 2)/(sqrt(方差+平均^ 2))+ sqrt(ln(1 +(方差)/(平均^ 2)))* Z) ?
我的SAS代码是:
/*I use StdDev^2 notation instead of variance here. */
DATA nonStLogNorm;
nonStLN = exp(1)**(log((mean**2)/(sqrt(StdDev^2 + mean**2)) +
sqrt(log(1 + (StdDev^2)/(mean**2))) * rand('UNIFORM'));
RUN;
参考文献:
Rick Wicklin的RAND
函数:
http://blogs.sas.com/content/iml/2013/07/10/stop-using-ranuni/
http://blogs.sas.com/content/iml/2011/08/24/how-to-generate-random-numbers-in-sas/
答案 0 :(得分:2)
您需要的是逆累积分布函数。这是与整个域上的分布的归一化积分相反的函数。因此,0%是您最负面的可能值,100%是您最积极的。实际上,虽然你会吝啬0.01%和99.99%之类的东西,或者类似的东西,否则你会在很多发行版中达到无限。
然后从那里你只需要随机输入一个范围(0,1)中的数字并将其插入到函数中。记得夹住它!
double CDF = 0.5 + 0.5*erf((ln(x) - center)/(sqrt(2)*sigma))
所以
double x = exp(inverf((CDF - 0.5)*2.0)*sqrt(2)*sigma + center);
应该为您提供所需的分发。 inverf是erf函数的反函数。这是一个常见的函数,但通常不在math.h中。
基于SIMD的随机数生成器是否需要进行分发。这样工作正常,假设我在输入时没有注意到某些东西,上面的工作就可以了。
根据要求如何钳制:
//This is how I do it with my Random class where the first argument
//is the min value and the second is the max
double CDF = Random::Range(0.0001,0.9999); //Depends on what you are using to random
//How you get there from Random Ints
unsigned int RandomNumber = rand();
//Conver number to range [0,1]
double CDF = (double)RandomNumber/(double)RAND_MAX;
//now clamp it to a min, max of your choosing
CDF = CDF*(max - min) + min;
答案 1 :(得分:1)
如果您希望从标准正态分布中提取Z
,是否应该通过调用RAND('NORMAL')
而不是RAND('UNIFORM')
来获取它?