再帰が何であるかを教えてくれませんでしたが、平方根、パウ、逆正弦、または逆余弦を使用している場合は、長い一連の操作でNaNを生成するのはかなり簡単です。
計算によって量が生成され、それx
をある角度θの正弦であると想定し、基礎となる数学x
が常に-1から1の間でなければならないことを示していると仮定します。の逆サインを取ることによってθを計算しx
ます。
問題は次のとおりです。コンピューターで行われる算術は、実数の算術の近似にすぎません。IEEE浮動小数点数による加算と乗算は推移的ではありません。1ではなく1.0000000000000002の値を取得する可能性がありx
ます。この値の逆サインを取得すると、NaNが取得されます。
標準的なトリックは、数値エラーに起因するニアミスから保護することです。asin
組み込みのacos
、、、、sqrt
およびを使用しないでくださいpow
。asin(1.0000000000000002)
やなどから保護するラッパーを使用しsqrt(-1e-16)
ます。NaNではなく前者のpi/2を作成し、後者をゼロにします。これは確かに応急修理であり、これを行うと問題が発生する可能性があります。問題が、計算が正しく定式化されていないことである場合はどうなりますか?1.0000000000000002を1として扱うことは正当ですが、100の値を1であるかのように扱わないことが最善です。ラッパーに対する100の値は、asin
1に切り捨てるのではなく、例外をスローすることによって最もよく扱われます。
無限大とNaNにはもう1つの問題があります。それらは伝播します。1回の計算でのInfまたはNaNは、すぐに数百、次に数千の値のInfまたはNaNになります。私は通常、浮動小数点演算を続行する代わりに、InfまたはNaNを取得するときに浮動小数点例外を発生させるようにします。(注意:浮動小数点の例外はC ++の例外ではありません。)これを行うと、シグナルハンドラーが配置されていない限り、プログラムが爆破されます。それは必ずしも悪いことではありません。デバッガーでプログラムを実行して、問題が発生した場所を正確に見つけることができます。これらの浮動小数点の例外がないと、問題の原因を見つけるのは非常に困難です。