2

非常に長い再帰 (約 50,000) といくつかの非常に大きなベクトル (double 型の長さも 50,000) を使用して、各再帰の結果を平均化する前に格納するプログラムを作成しています。プログラムの最後に、数値が出力されることを期待しています。

ただし、得られた結果の一部は「ナン」でした。不思議なことに、再帰の回数を減らすと、プログラムは問題なく動作します。だから私はこれがベクトルのサイズと関係があるかもしれないと推測しています. 私の質問は、非常に長いベクトル (または配列) でオーバーフローが発生した場合、どのような影響があるでしょうか? 私の場合と同じように、「ナン」を取得しますか?

私のプログラムに関するもう 1 つの不可解な点は、さらに大きな再帰 (100,000) をいくつか試してみましたが、出力は正常だったことです。しかし、ベクトルに格納されている各数値が大きくなるようにパラメーター値を変更すると (依然として double 型ですが)、出力は "nan" になります。ベクトルの最大容量は、格納する数値のサイズに依存しますか?

4

2 に答える 2

3

再帰が何であるかを教えてくれませんでしたが、平方根、パウ、逆正弦、または逆余弦を使用している場合は、長い一連の操作でNaNを生成するのはかなり簡単です。

計算によって量が生成され、それxをある角度θの正弦であると想定し、基礎となる数学xが常に-1から1の間でなければならないことを示していると仮定します。の逆サインを取ることによってθを計算しxます。

問題は次のとおりです。コンピューターで行われる算術は、実数の算術の近似にすぎません。IEEE浮動小数点数による加算と乗算は推移的ではありません。1ではなく1.0000000000000002の値を取得する可能性がありxます。この値の逆サインを取得すると、NaNが取得されます。

標準的なトリックは、数値エラーに起因するニアミスから保護することです。asin組み込みのacos、、、、sqrtおよびを使用しないでくださいpowasin(1.0000000000000002)やなどから保護するラッパーを使用しsqrt(-1e-16)ます。NaNではなく前者のpi/2を作成し、後者をゼロにします。これは確かに応急修理であり、これを行うと問題が発生する可能性があります。問題が、計算が正しく定式化されていないことである場合はどうなりますか?1.0000000000000002を1として扱うことは正当ですが、100の値を1であるかのように扱わないことが最善です。ラッパーに対する100の値は、asin1に切り捨てるのではなく、例外をスローすることによって最もよく扱われます。

無限大とNaNにはもう1つの問題があります。それらは伝播します。1回の計算でのInfまたはNaNは、すぐに数百、次に数千の値のInfまたはNaNになります。私は通常、浮動小数点演算を続行する代わりに、InfまたはNaNを取得するときに浮動小数点例外を発生させるようにします。(注意:浮動小数点の例外はC ++の例外ではありません。)これを行うと、シグナルハンドラーが配置されていない限り、プログラムが爆破されます。それは必ずしも悪いことではありません。デバッガーでプログラムを実行して、問題が発生した場所を正確に見つけることができます。これらの浮動小数点の例外がないと、問題の原因を見つけるのは非常に困難です。

于 2012-10-07T14:07:14.110 に答える
2

計算の正確な性質に依存します。NaN でない数値を足し算しても、結果も NaN にはなりません。+infinityかもしれませんが。

ただし、たとえば、計算の一部が +infinity を生成し、別の -infinity を生成し、後でこれら 2 つの結果を追加すると、NaNが得られます。

アーキテクチャが IEEE 754 に準拠していると仮定すると、このhttp://en.wikipedia.org/wiki/NaN#Creationは、算術演算が NaN を返す状況を示しています。

于 2012-10-07T12:59:55.537 に答える