私はIEEE-754委員会のメンバーだったので、少しわかりやすくするように努めます。
まず、浮動小数点数は実数ではなく、浮動小数点演算は実数演算の公理を満たしていません。トリコトミーは、浮動小数点数に当てはまらない実際の算術の唯一の特性ではなく、最も重要なものですらありません。例えば:
- 加算は関連付けされていません。
- 分配法は成立しません。
- 逆のない浮動小数点数があります。
私は続けることができました。私たちが知っていて気に入っている実際の算術のすべての特性を満たす固定サイズの算術型を指定することはできません。754委員会はそれらのいくつかを曲げるか壊すかを決定しなければなりません。これは、いくつかのかなり単純な原則によって導かれます。
- 可能な場合は、実際の算術の動作と一致させます。
- 不可能である場合は、違反をできるだけ予測可能かつ診断しやすいように努めます。
「正解が間違っているわけではない」というコメントについては、これは誤りです。述語(y < x)
は、y
がより小さいかどうかを尋ねx
ます。場合はy
NaNである、それはありません以下の任意の浮動小数点値よりもx
、その答えは必然的に偽です。
トリコトミーは浮動小数点値には当てはまらないと述べました。ただし、同様のプロパティが保持されます。754-2008標準の5.11節、パラグラフ2:
以下の4つの相互に排他的な関係が可能です:より小さい、等しい、より大きい、および順序付けされていない。最後のケースは、少なくとも1つのオペランドがNaNの場合に発生します。すべてのNaNは、順序付けなしで、それ自体を含むすべてのものと比較します。
NaNを処理する追加のコードを書く限り、NaNが適切に機能するようにコードを構造化することは(常に簡単ではありませんが)通常は可能ですが、常にそうであるとは限りません。そうでない場合、追加のコードが必要になる場合がありますが、代数的クロージャが浮動小数点演算にもたらした利便性を犠牲にしても、それはわずかな代償です。
補遺:多くのコメンターは、NaNを採用することを理由に、平等性と三分法の反射性を維持する方がより有用であると主張しています!= NaNはおなじみの公理を維持しないようです。私はこの見方に同情することを自白しているので、私はこの答えをもう一度見て、もう少しコンテキストを提供すると思いました。
Kahanとの会話からの私の理解は、NaN!= NaNは2つの実用的な考察から生じたということです。
これx == y
は、可能な場合はx - y == 0
常に同等である必要があります(実際の算術の定理であることに加えて、これにより、ハードウェアによる比較の実装がスペース効率が向上します。これは、標準が開発されたときに最も重要でした。ただし、これはxに違反しています。 = y =無限大なので、それ自体は大きな理由ではありません(x - y == 0) or (x and y are both NaN)
。
さらに重要なこととしてisnan( )
、当時、NaNが8087の算術演算で公式化されたという述語はありませんでした。isnan( )
何年もかかるようなプログラミング言語に依存しないNaN値を検出する便利で効率的な手段をプログラマーに提供する必要がありました。この件に関するKahan自身の文章を引用します。
NaNを取り除く方法がなければ、それらはCRAYのIndefinitesと同じくらい役に立たないでしょう。問題が発生するとすぐに、計算を無期限に継続するのではなく、無期限に終了するまで停止するのが最善です。そのため、NaNに対する一部の演算は非NaN結果を提供する必要があります。どの操作ですか?…例外はC述語「x == x」と「x!= x」であり、これらはそれぞれ、無限または有限の数xごとに1と0ですが、xが非数(NaN)の場合は逆になります。これらは、NaNの単語と述語IsNaN(x)を欠く言語のNaNと数値の間の唯一の単純で例外のない区別を提供します。
これは、「Not-A-Boolean」のようなものを返すことを除外するロジックでもあることに注意してください。多分この実用主義は見当違いであり、標準が必要isnan( )
とすべきだったかもしれませんが、世界がプログラミング言語の採用を待っている間、NaNを数年にわたって効率的かつ便利に使用することはほぼ不可能でした。それが妥当なトレードオフだったとは私は思いません。
率直に言うと、NaN == NaNの結果は今は変わりません。インターネットで文句を言うよりも、それと一緒に暮らすことを学ぶ方が良いです。コンテナーに適した順序関係も存在する必要があると主張したい場合は、お気に入りのプログラミング言語totalOrder
でIEEE-754(2008)で標準化された述語を実装することをお勧めします。それが現在の状況を動機づけたカハンの懸念の妥当性をまだ語っていないという事実。
while (fabs(x - oldX) > threshold)
、収束が発生するかNaNが計算に入るとループを終了します。NaNの検出と適切な対策は、ループの外側で行われます。