我偶尔会在此方法中获得stackoverflow异常。
double norm_cdf(const double x) {
double k = 1.0/(1.0 + 0.2316419*x);
double k_sum = k*(0.319381530 + k*(-0.356563782 + k*(1.781477937 + k*(-1.821255978 + 1.330274429*k))));
if (x >= 0.0) {
return (1.0 - (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x) * k_sum);
} else {
return 1.0 - norm_cdf(-x);
}
}
有关为什么我可能会得到它的任何建议?我可以采取哪些措施来纠正错误?
答案 0 :(得分:24)
您的问题是x
不是数字时。 NAN >= 0.0
为假,-NAN >= 0.0
也是假的。
你可以像其他人所建议的那样特别检查NAN,但我建议简化:
static double norm_cdf_positive(const double x) {
double k = 1.0/(1.0 + 0.2316419*x);
double k_sum = k*(0.319381530 + k*(-0.356563782 + k*(1.781477937 + k*(-1.821255978 + 1.330274429*k))));
return (1.0 - (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x) * k_sum);
}
double norm_cdf(const double x) {
if (x >= 0.0) {
return norm_cdf_positive(x);
} else {
return 1.0 - norm_cdf_positive(-x);
}
}
这样做的好处是编译器可以对其行为做出更明智的假设。请注意,我已将“内部”函数标记为静态(将其范围限制为当前编译单元)。您还可以使用未命名的命名空间。 (编辑:实际上Timothy Shields有一种更简单的方法可以删除递归,这可以将所有内容保存在一个函数中)
答案 1 :(得分:15)
可能这种方法只是打破骆驼背部的稻草。这个函数最多只调用一次,所以不是问题。 (编辑:或者是其他人指出的NAN问题,将导致无限递归。)
无论如何,您可以轻松地使函数不递归,这可能是一个更简单的选项。
double norm_cdf(double x) {
bool negative = x < 0;
x = abs(x);
double k = 1.0/(1.0 + 0.2316419*x);
double k_sum = k*(0.319381530 + k*(-0.356563782 + k*(1.781477937 + k*(-1.821255978 + 1.330274429*k))));
double result = (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x) * k_sum;
if (!negative)
result = 1.0 - result;
return result;
}
答案 2 :(得分:8)
当x
为NaN
时,递归永远不会终止。添加一个检查:C ++ 11中的std::isnan
,或者懒惰的x != x
或文档和责任用户。如果您选择处理NaN
,那么传播它可能是一个明智的选择。