我尝试使用C#编写此函数:
和我不确定我的代码是否正确以解决此问题
这是我尝试编写的方法代码:
public double PDF()
{
// output variable
double result = 0.0;
// inputs
double Segma = 0.35;
double M = 14.45;
double x = 0.0;
Random rnd = new Random();
x = rnd.NextDouble();
double LeftBase = 1/(Math.Sqrt(2*Math.PI)*Segma*x);
double RightEx = (-1 * Math.Pow((Math.Log(x) - M), 2)) / (2 * (Math.Pow(Segma, 2)));
result= LeftBase * Math.Exp(RightEx);
return result;
}
我尝试在for循环中测试此方法,但它总是返回0值,我认为返回值小于容纳 double 变量
任何人都帮我解决这个问题并获得返回值
答案 0 :(得分:1)
问题出在这里:
Math.Exp(RightEx);
此时,RightEx
的值为-966.1
(约)
使用double
,e^-966.1
将返回0.
请注意,如果您从指定的公式替换sigma(1.37)和mu(8.35)的值,您将从PDF()获得〜0.00000000000000013088463858575497的返回值(仍然非常小,但至少它不是零)。
答案 1 :(得分:0)
这应该是normal distribution(又名“钟形曲线”)吗?如果是,您的公式和编码不正确。没有Log
功能。
我想知道为什么你会为平均值和标准偏差硬编码这两个常量。如果您传递了这些函数,那么这将是一个更普遍有用的函数,因此您可以在许多不同的情况下使用它。
我建议你写x*x
而不是Math.Pow(x, 2)
。
public double LogNormal(double x, double mu, double sigma) {
// check to see if x is less than zero and do something - throw exception, etc.
double denom = 1.0/Math.Sqrt(2*Math.PI)*sigma*x);
double expon = (Math.Log(x)-mu)/Math.Sqrt(2.0)/sigma;
return Math.Exp(-expon*expon)/denom;
}
不是将对Random
的调用嵌入函数中,而是将其传递给它。
答案 2 :(得分:0)
在图片中,sigma定义为1.37,而在实现中,定义为0.35。此外,mu(在实现中称为M)定义为14.45,而在图片中定义为8.35。
答案 3 :(得分:0)
在处理指数pdf时,这是一个非常常见的问题。一般来说,exp(。)内的值的大小太高。如果你试图计算高斯密度,那么配方就是错误的,你应该从配方中删除ln()。
然而,如果这是一个特殊情况(或另一个pdf)并且公式是正确的,那么我将问这个计算的原因。如果你不需要结果的确切值,并且只使用返回的变量进行比较(例如找到pdf的峰值索引等),那么你可以做这个数学技巧:
如果将整个公式封装在' ln()'配方将成为;
ln(LeftBase * Math.Exp(RightEx)) - > LN(LeftBase)+ LN(Math.Exp(RightEx)) - ln& exp相互抵消 - > ln(LeftBase)+ RightEx
通过执行此操作,您现在可以使用与零不同的数字,并且可以根据需要比较返回的结果。
答案 4 :(得分:0)
这不是一个解决方案,只是建议更清晰,更有效的编码:
double Normal(double X, double Mu, double Sigma)
{
Sigma= 1. / Sigma;
X= (X - Mu) * Sigma;
return Math::Exp(- 0.5 * X * X) * 0.398942280401432678 * Sigma;
}
double LogNormal(double X, double Mu, double Sigma)
{
return X == 0 ? 0 : Normal(Math::Log(X), Mu, Sigma) / X;
}