この回答のポイントは、Math.min
完全に可換であるという言語設計の選択が理にかなっている理由を説明することです。
-0 < 0 が発生する理由を知りたいですか?
そうではありません。<
は「最小」とは別の操作であり、 のような IEEE 比較Math.min
だけに基づいているわけではありません。<
b<a ? b : a
それは可換ではないでしょう。NaN と符号付きゼロ。(<
いずれかのオペランドが NaN の場合は false であるため、 が生成されa
ます)。
最小の驚きの原則に関する限り、それは少なくとも同じくらい驚くべきことです (それ以上ではないにしても)Math.min(-1,NaN)
でしNaN
たがMath.min(NaN, -1)
でした-1
.
JS 言語の設計者はMath.min
NaN 伝播を望んでいたため、<
とにかくそれをベースにすることはできませんでした。 彼らは、符号付きゼロを含めて完全に交換可能にすることを選択しましたが、これは賢明な決定のようです。
OTOH、ほとんどのコードは符号付きゼロを気にしないため、この言語設計の選択は、誰かが明確に定義された符号付きゼロのセマンティクスを必要とするまれなケースに対応するために、誰もが少しパフォーマンスを犠牲にします.
配列内の NaN を無視する単純な操作が必要な場合は、 を繰り返しますcurrent_min = x < current_min ? x : current_min
。これはすべての NaN を無視-0
し、for current_min <= +0.0
(IEEE 比較) も無視します。または、current_min
NaN で開始すると、NaN のままになります。これらの多くは関数にとって望ましくないためMath.min
、そのようには機能しません。
他の言語を比較すると、C の標準fmin
関数は可換 wrt です。NaN (非 NaN がある場合は JS の反対を返す) ですが、可換である必要はありません。ゼロを署名しました。fmin
一部の C 実装は、 /に対して +-0.0 に対して JS のように動作することを選択しますfmax
。
しかし、C++std::min
は純粋に<
操作の観点から定義されているため、そのように機能します。(文字列などの非数値型を含め、一般的に機能することを意図してstd::fmin
います。FP 固有の規則がないのとは異なります。) x86 でブランチレス FP の最小値と最大値を与える命令は何ですか? を参照してください。re: x86 のminps
命令と C++std::min
はどちらも可換ではありません。NaN および符号付きゼロ。
IEEE 754<
では、個別の FP 番号に対する合計順序は示されません。Math.min
は NaN を除きます (たとえば、 と を使用してソート ネットワークを構築した場合Math.max
)。その順序は と一致しません。Math.max
どちらも NaN があれば NaN を返すため、最小/最大コンパレータを使用するソート ネットワークは、入力配列。
Math.min
どの引数が返されたかを確認するようなものなしでは、それだけではソートには十分ではありませんが==
、それは NaN だけでなく符号付きゼロでも機能しません。