2

これは、 IEEE754 NaN 値に対して false を返すすべての比較の根拠は何ですか?へのフォローアップの質問です。(これはコメントよりも別の質問の方が良いと思います)。それはちょうど1つの重要なことを欠いている非常に良い答えを持っています:なぜNaN != NaNですか?

NaN は数値と比較して順序付けされていないためNaN < xNaN > x両方とも常に false であることを理解しています。しかし、それはなぜ平等が後退しているのかを説明していません。私がリンクした質問の答えを引用するには:

次のようなものを提供するプログラミング言語に依存しない NaN 値を検出するための便利で効率的な手段をプログラマーに提供する必要がありました。isNan()

わかりました。

if((0/0) == x) print "I found NaN!";
//using 0/0 is more readable than using 0x7fc00000 or 0x7ff8000000000000

これは便利で効率的で、プログラミング言語が提供する構造に依存しません。プログラミング言語にグローバル NaN が定義されていない場合でも、ローカル (またはグローバル) 変数を自分で簡単に作成できます。

特にFPUにはハードコードされた応答があるため(計算は必要ありません)、単一の余分な操作は確かに非効率的ではありません。0/0 を使用することは、 非論理的 よりもプログラマにとって便利ですx!=x

プログラムが NaN をチェックする必要はめったになく、チェックごとに余分な操作が 1 つあることがプログラムの非効率の理由にはなりません。同様に、単一の余分な変数、特に一時的な変数を処理できないほど抑制されたプログラムはありません。

私にとって、「NaN!=NaN検出できるようにする必要がある」という議論は意味がありませんInfinity!=Infinity。「検出できるようにする必要がある」という議論とまったく同じです。いいえ、他の人と同じように 1/0 と比較してください。

したがって、私の質問は元の質問よりもはるかに狭いです:なぜNaN != NaNですか?

元の質問と重複するものがたくさんあるため、これが以前に尋ねられたかどうかはわかりません。

サイドノート:

NaN == NaN今は変わらない

FPU は現在変更されませんが、一部のプログラミング言語は既に変更されているため、それNaN == NaNは事実です。

編集:

これまでに回答を受け入れなかった理由を明確にさせてください。これまでのコメントを読みましたが、申し訳ありませんが、ボールを落としてしまいました。同意しない理由を説明する代わりに、「なぜ」と尋ねただけで、別の理由を教えてください. それでは、私の見解をよりよく説明してみましょう。

Infinity と NaN は多くの点で似ています。

  1. Infinity と NaN はどちらも概念です。無限は数ではなく、終わりのない概念です。x が Infinity の場合、x が無限であることを表します。NaN は数値ではなく (duh)、無効な状態または数学的に有効でないものを表します。数学的な完全性のために: 無限大は議論の余地のある「数」ですが、浮動小数点数は実数に近似し (有理数に近いですが)、無限大は明らかに実数ではありません。したがって、FPU と実数直線に関する限り、無限大 (すべての型) は数ではありません (ドメインの「数」の定義による)。
  2. 等しいということは、常に数値が等しいというわけではありません。FPU が比較を実行するように要求された場合でも、両方のオペランドが数値 (概念ではない) である場合、一般的な等価性は数値の等価性のみです。一方のオペランドが Infinity または NaN の場合、もう一方が同じ概念を表しているかどうかを確認するために、一般的な等価性が使用されます。たとえば、x == Infinity数値の等価性を使用しません (無限大は数値ではないため) 代わりに、x が正の無限大の概念を表しているかどうかを確認します。同様に、 x が「非数」の概念である場合、まったく同じことがx == NaNtrue を返すことを期待しますが、そうではありません(なぜこの質問のポイントなのか)。
  3. どちらも 0 で割ることで取得できます。0/0 は NaN を返し、1/0 は Infinity を返します。あなたの言語に Infinity の定数がない場合x == (1/0)は、x と Infinity を比較する方法です。
  4. 複数のフレーバー。Infinity には無数の種類があります (カーディナリティのため)。ただし、FPU には区別がありません。Infinity は汎用的なものであり、利用できる唯一のものです。これらの構成では、たとえば x が可算無限大かどうかを尋ねることはできません。NaN には、概念的には 1 つの型しかありませんが (「数ではない」)、2 つの処理方法があります: 静寂とシグナリングです。私はシグナリングについて何も知りませんが、シグナリング NaN の等価性を比較しようとすると、それがスローすることになるため、等価性がないため、完全に話題になっているわけではありません。
  5. ビット表現。NaN にはさまざまなビット表現がありますが、Infinity には 1 (-Infinity の場合は 1) しかありません。ただし、NaN のすべての表現は、「非数」という同じ概念を表しているため、論理的にはまったく同じ値です。0x7FF8000000000000 と 0x7FF8000000000001 を区別する必要はありません。これらはまったく同じことを意味し、まったく同じ計算でどちらの結果も返すことができます。x が sqrt(-1) なのか、それとも x が log(-1) なのかを尋ねることはできません。どちらもまったく同じ NaN を返すからです。Infinity が 1 種類しかないのと同様に、(静かな) NaN も 1 種類しかありません。はい、複数のビット表現がありますが、1 つが他の表現よりも大きくはありません。FPU は特別なロジックを使用して、それらをすべてまったく同じように扱います。これは、+0 とは異なるビットを持つがまったく同じように扱われる -0 にも同様に当てはまります。したがって、ビットは論理的等価性とは関係のない実装の詳細です。
  6. (トピック外ですが、どちらも特別な数学を持っています: x-1Infinity または NaN の値を変更しません)。

はい、あなたが「平等は数字ではないので意味がない」と言ったのを聞いたことがありますが、それが本当なら#1のように無限大を比較するのも意味がないので、その声明には同意しません(これも数字ではありません)。#2のように、非数値を比較することは理にかなっていますが。

実際、元の質問に対するすべての回答を読みました (および、NaN とは異なり、なぜ浮動小数点の無限大は等しいのですか?には関連する回答がいくつかあります)。真である理由のすべての引数は、NaN != NaN「数字ではないため」(既に対処済み) または「さまざまなビット表現が多数あるため」のいずれかに要約されますが、これは #5 によって反論されます。

NaN が異なる等式を持つ必要がある理由の論理的根拠は考えられません。すべてを説明したと言っているわけではありません。私の主張の 1 つが間違っているのでしょうか、それとも私が考えもしなかった別の理由があるのでしょうか? だからこそ、私は「なぜ」という言葉にキャンプを張ってきました。同意しない場合は、私に反論するか、あなたの主張を弁護してください。上記の論理に対して少なくとも 1 つの反論があると思いますが、それを聞くのを楽しみにしています。

ずっと考えていたので、元の質問にこれらを含めなかったことをもう一度お詫びします。また、これにより既存の回答が大きく変わる可能性があることも申し訳ありません。

4

1 に答える 1

3

生成にはいくつかの方法がありますNaN

これを想像してください:

double expr1 = 0.0 / 0.0;
double expr2 = Math.log(-1.0);
if (expr1 == expr2) {
  // They are the same
}

これら 2 つNaNの は、数値として表現できた場合、異なる値になる可能性が高くなります。

保持される場合NaN == NaN、このスニペットは、それらを等しいと比較するという予期しない結果をもたらします。ほとんどのプログラムは、期待どおりに比較を行うため (したがって、 , を使用します==が、<=,は使用しません) !==!<=返さfalseれても、これらのプログラムが間違ったことを結論付けることはありません。

于 2016-06-13T21:29:51.080 に答える