すべての比較で IEEE754 NaN 値に対して false が返される根拠は何ですか?
-
21-09-2019 - |
質問
NaN 値の比較が他のすべての値と異なる動作をするのはなぜですか?つまり、一方または両方の値が NaN である演算子 ==、<=、>=、<、> とのすべての比較は、他のすべての値の動作とは逆に false を返します。
これは何らかの形で数値計算を簡素化しているのだと思いますが、明示的に述べられた理由は見つかりませんでした。 IEEE 754の現状に関する講義ノート Kahan によるその他の設計上の決定について詳しく説明しています。
この逸脱した動作により、単純なデータ処理を実行するときに問題が発生します。たとえば、レコードのリストをソートする場合、C プログラム内のいくつかの実数値フィールドでは、NaN を最大要素として処理するために追加のコードを記述する必要があります。そうしないと、ソート アルゴリズムが混乱する可能性があります。
編集:これまでの回答はすべて、NaN を比較するのは無意味であると主張しています。
私は同意しますが、それは正しい答えが虚偽であることを意味するものではなく、それは幸運にも存在しないブール(NAB)ではありません。
したがって、比較のために真またはfalseを返すことの選択は私の見解ではarbitrary意的であり、一般的なデータ処理の場合、通常の法則(==、<、==、>の三で切開)に従うと有利です。これらの法律に依存していることは混乱します。
したがって、私は単なる哲学的推論ではなく、これらの法律を破ることによって得られる具体的な利点を求めています。
編集2:NaN を最大値にすることがなぜ悪い考えであり、上限の計算が台無しになるのかが理解できたように思います。
NaN != NaN は、次のようなループでの収束の検出を避けるために望ましい場合があります。
while (x != oldX) {
oldX = x;
x = better_approximation(x);
}
ただし、絶対差を小さな制限と比較して記述する方がよいでしょう。したがって、私の意見では、これは NaN での再帰性を破壊するための比較的弱い議論です。
解決
私は 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 算術で形式化されたときの述語。次のようなものを提供する、プログラミング言語に依存しない NaN 値を検出する便利で効率的な手段をプログラマーに提供する必要がありました。isnan( )
それには何年もかかるかもしれません。この件に関するカーハン自身の文章を引用します。
NaN を取り除く方法がなかった場合、NaN は CRAY の不定値と同じくらい役に立たなくなります。計算は、不定の結論に至るまで無期限に継続するのではなく、遭遇したらすぐに停止するのが最善です。そのため、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) で標準化された述語。現在の状況を引き起こしたカーハン氏の懸念の正当性をまだ物語っていないという事実。
他のヒント
NaNは、未定義状態/数と考えることができます。 0/0である未定義またはSQRTの概念に似(-3)(実数システムにおける場合の浮動小数点命)。
のNaNは、この未定義の状態のプレースホルダの一種として使用されます。数学的に言えば、undefinedに未定義等しくされていません。どちらも、あなたは未定義の値が他の未定義の値よりも大きいか小さいと言うことはできません。したがって、すべての比較はfalseを返します。
この現象は、SQRT(-2)にSQRTを(-3)比較の場合にも有利です。彼らは両方のリターンNaNのだろうが、彼らは同じ値を返していても同じではありません。そのためのNaNを扱うときに常にfalseを返す平等を持つことは望ましい動作です。
。私はあなたに2つのボックスを渡し、それらのどちらもリンゴが含まれていることを教えてくれた場合は、ボックスは同じものを含んでいることを教えてでしょうか?
NaNはそれがないだけで何、何かが何であるかについての情報が含まれていません。したがって、これらの要素は確かに等しくなるように言われることはありません。
ウィキペディアの記事より NaN, 、次の方法では NaN が発生する可能性があります。
- 少なくとも 1 つのオペランドとして NaN を使用するすべての数学演算>
- 区分 0/0、∞/∞、∞/-∞、-∞/∞、および -∞/-∞
- 乗算 0×∞ と 0×-∞
- 加算 ∞ + (-∞)、(-∞) + ∞ および同等の減算。
- 関数をドメイン外の引数に適用する。これには、負の数の平方根を取る、負の数の対数を取る、90 度 (または π/2 ラジアン) の奇数倍の正接を取る、または逆正弦を取るなどの行為が含まれます。 -1 未満または +1 より大きい数値のコサイン。
これらの操作のどれが NaN を作成したかを知る方法がないため、意味のある比較方法はありません。
私は、設計根拠を知っているが、ここではIEEE 754-1985標準からの抜粋ですありません。
「オペランド形式が異なっていても、すべてのサポートされる形式で浮動小数点数を比較することが可能でなければならない比較は正確な、決してオーバーフローやアンダーフローしている四つの相互に排他的な関係が考えられます。より大きい、等しい、未満少なくとも一つのオペランドがNaNであるとき、そして順不同。最後のケースが発生した。すべてのNaNで自身を含むすべてのもの、と順不同比較するものとする。」
NaN を許可するほとんどのプログラミング環境では 3 値ロジックも許可しないため、奇妙に見えるだけです。3 値のロジックを混合に投入すると、一貫性が得られます。
- (2.7 == 2.7) = 真
- (2.7 == 2.6) = false
- (2.7 == NaN) = 不明
- (NaN == NaN) = 不明
.NET でも提供されていません。 bool? operator==(double v1, double v2)
オペレーターだから、あなたはまだ愚かなことで立ち往生しています (NaN == NaN) = false
結果。
私はNaN(非Aナンバー)を正確にすることを意味すると推測しています。
これはnull
オペランドとSQLでビット算術演算のようなものです:。彼らnull
内のすべての結果
浮動小数点数のための比較は数値を比較します。したがって、それらは非数値のために使用することはできません。 NaNは従って数値の意味で比較することはできない。
オーバー簡素化の答えがNaNが何の数値を持っていないので、他のものと比較することで何もないということです。
あなたは彼らが+ INFのように行動したい場合は、あなたはのためにテストし、+ INFを使用してNaNを置き換えることを検討することがあります。
NaNは(ランタイムエラーの特別な種類の)暗黙の新しいインスタンスです。手段はNaN !== NaN
その同じ理由new Error !== new Error
こと。
と心などimplicitnessでクマも外のエラーを見て、例えば正規表現の文脈で、それは/a/ !== /a/
new RegExp('a') !== new RegExp('a')
を意味し、 は、私は自分自身ではNaNを比較するためだけの原因があると思います。どのように、例えば一つは、シグナリングNaNを静かなNaNの違いを発見するのですか?我々は、ブール値(すなわち、Aビット・ベクトル)のセットとして信号を考える場合は、1つは、十分ビットベクトルは、同一又は異なって順序セットに応じているかどうかを尋ねるかもしれません。例えば、仮数が残っていた場合、最大バイアス指数を復号化するにバイナリ形式の最上位ビットに仮の最上位ビットを整列させるように、負の値は静かのNaNと任意の正の値になるであろうようにシフトシグナリングはNaNです。当然のゼロは無限大のために予約されており、比較が順不同になります。 MSB位置合わせは、異なるバイナリ形式からの信号の直接比較を可能にするであろう。信号の同じセットを持つ2つのNaNため、同等であると平等に意味を与えるだろう。
数学は番号が「ただ存在する」フィールドであるため。 あなたのコンピューティングのニーズに応じて、の初期化のこれらの数字とのキープの自分の状態なければなりません。 それらの古い日目にメモリの初期化は、あなたが頼ることができませんでした方法で働いていました。あなたがのを「ああ、それは0xCDですべての時間を初期化されるだろう、私のアルゴが壊れていないだろう」自分がこれについて考えることができない可能性が決してます。
あなたが正しい必要があるので、<全角> の溶剤非混合の粘着性が十分でのあなたのアルゴリズムをさせないことではないしに吸い込まと壊れてばかりです。 数を含む良いアルゴリズムは、ほとんどの関係で仕事に行くされており、それらのの場合()は、の関係は省略されます。
これはあなたの代わりにコンピュータのメモリからランダム地獄をプログラミングする、作成時に新しい変数に置くことができるだけのグリースです。そして、それが何であれ、あなたのアルゴリズムは、中断されません。
あなたがまだ突然、あなたのアルゴリズムはNaNを生成していることを見つける次に、一度にすべての枝1に探して、それを一掃することが可能です。ここでも、「常にfalse」のルールは、この中で多くのことを助けている。
私にとっては、それを説明する最も簡単な方法はあります:
私は何かを持っており、それはリンゴではない場合、それはオレンジ色ですか?
あなたが何か他のものではNaNを比較することはできません(でも、それ自体)それが値を持っていないため。また、それは(数除く)任意の値とすることができる。
私が何かを持って、それは数に等しくない場合、それは文字列です?
非常に短い答えます:
次のようなので:
nan / nan = 1
保有してはなりません。そうでなければinf/inf
は1になります。
(したがってnan
がnan
に等しくすることができない。よう>
又は<
ため、nan
はアルキメデスの性質を満たす組における任意の順序関係を尊重するならば、我々は再び限界でnan / nan = 1
有するであろう)。