8

このメソッドでスタックオーバーフロー例外が発生することがあります。

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);
    }
}

なぜ私がそれを手に入れているのかについて何か提案はありますか? エラーを修正するために実行できる手順はありますか?

4

3 に答える 3

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);
    }
}

これには、コンパイラがその動作についてより賢明な仮定を行うことができるという利点があります。「内部」関数を static としてマークしたことに注意してください (これにより、そのスコープは現在のコンパイル単位に制限されます)。名前のない名前空間を使用することもできます。(編集: 実際、Timothy Shields には再帰を削除する簡単な方法があり、すべてを 1 つの関数にまとめています)

于 2013-08-09T20:20:30.317 に答える
8

xがの場合NaN、再帰は終了しません。チェックを追加します: std::isnanC++11、または lazy x != x、または document-and-blame-user のいずれかで。を処理することを選択した場合NaN、それを伝播することは賢明な選択かもしれません。

于 2013-08-09T20:18:52.683 に答える