Raj*_*war 8 c++ stack-overflow
我偶尔会在此方法中获得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);
}
}
Run Code Online (Sandbox Code Playgroud)
为什么我可能得到它的任何建议?我可以采取哪些措施来纠正错误?
Dav*_*ave 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);
}
}
Run Code Online (Sandbox Code Playgroud)
这样做的好处是编译器可以对其行为做出更明智的假设.请注意,我已将"内部"函数标记为静态(将其范围限制为当前编译单元).您还可以使用未命名的命名空间.(编辑:实际上Timothy Shields有一种更简单的方法来删除递归,它将所有内容保存在一个函数中)
Tim*_*lds 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;
}
Run Code Online (Sandbox Code Playgroud)
当x是NaN时,递归将永远不会终止.添加一个检查:std::isnan在C++ 11中,或者是懒惰的x != x,或者是文档和责任用户.如果你选择处理NaN,传播它可能是一个明智的选择.