web-dev-qa-db-ja.com

IEEE754標準でゼロで除算すると無限の値になるのはなぜですか?

興味がありますが、IEEE-754でゼロ以外の浮動小数点数をゼロで割ると、無限の値になるのはなぜですか?数学的な観点からはナンセンスです。したがって、この操作の正しい結果はNaNだと思います。

関数f(x) = 1/xは、xが実数の場合、x = 0の場合は定義されません。たとえば、関数sqrtは負の数に対して定義されておらず、sqrt(-1.0 f)IEEE-754NaN値を生成する場合。ただし、1.0f/0はInfです。

しかし、何らかの理由で、これはIEEE-754には当てはまりません。これには理由があるはずです。おそらく、最適化や互換性の理由がいくつかあります。

それで、ポイントは何ですか?

42
Evgeny Lazin

数学的な観点からはナンセンスです。

はい。いいえ。

重要なのは、浮動小数点数は概算です。広範囲の指数と限られた桁数を使用して、完全に間違っていない結果を取得したいとします。 :)

IEEE-754の背後にある考え方は、すべての操作が、起こりうる問題を示す「トラップ」をトリガーする可能性があるということです。彼らです

  • 違法(負の数のsqrtのような無意味な操作)
  • オーバーフロー(大きすぎる)
  • アンダーフロー(小さすぎる)
  • ゼロ除算(気に入らないもの)
  • 不正確(精度が低下しているため、この操作では間違った結果が得られる可能性があります)

現在、科学者やエンジニアのような多くの人々は、トラップルーチンを書くことに煩わされることを望んでいません。そのため、IEEE-754の発明者であるKahanは、トラップルーチンが存在しない場合、すべての操作で適切なデフォルト値を返す必要があると判断しました。

彼らです

  • 不正な値のNaN
  • オーバーフローの署名された無限大
  • アンダーフローの符号付きゼロ
  • 不確定な結果(0/0)のNaNと(x/0 x!= 0)の無限大
  • inexactの通常の操作結果

問題は、すべての場合の99%でゼロがアンダーフローによって引き起こされるため、数学的な観点から間違っていても、すべての場合の99%で無限大が「正しい」ということです。

58
Thorsten S.

なぜこれがナンセンスだと信じるのかわかりません。

a / bの単純な定義は、少なくともゼロ以外のbの場合、に到達する前にbから減算する必要があるasの一意の数です。ゼロ。

これをbがゼロになる可能性がある場合に拡張すると、ゼロになるためにゼロ以外の数値から減算する必要のある数値は実際無限大になります。 決して取得しないゼロに。

それを見る別の方法は、限界の観点から話すことです。正の数nがゼロに近づくと、式1 / nは「無限大」に近づきます。私は無限大が実際には具体的な数であるという妄想を広めないことを固く信じているので、私がその言葉を引用したことに気付くでしょう:-)

NaNは、数値を他の値(無限大を含む)で(おおよそでも)表すことができない状況のために予約されており、他のすべての値とは異なると見なされます。

たとえば、0 / 0(上記の単純な定義を使用)では、anybからasの量を引いて0にすることができます。したがって結果は不確定です。 -1、7、42、3.14159、またはその他の値にすることができます。

同様に、IEEE754で使用される実平面では値を持たない負の数の平方根のようなもの(そのためには複素平面に移動する必要があります)は表現できません。

9
paxdiablo

数学では、ゼロには符号がないため、ゼロによる除算は定義されていません。したがって、負の無限大または正の無限大(両方ではない)の2つの結果が等しく可能であり、排他的です。

(ほとんどの)コンピューティングでは、0.0には符号があります。したがって、私たちはどの方向から近づいているのか、そして無限大がどのような兆候を持っているのかを知っています。これは、0.0がゼロ以外の値を表し、システムで表現するには小さすぎる場合に特に当てはまります。これはよくあることです。

NaNが適切なのは、分母が本当に正確にゼロであることをシステムが確実に認識している場合のみです。そして、それを指定する特別な方法がない限り、それはできません。それはオーバーヘッドを追加します。

6
Approximatura

[〜#〜] note [〜#〜]:@ Cubicからの貴重なコメントに従って、これを書き直しました。

これに対する正しい答えは、微積分と限界の概念から来なければならないと思います。 f(x)/g(x)を仮定して、g(0) == 0の制限を_x->0_と見なします。ここで興味深い2つの大きなケースがあります。

  1. f(0) != 0の場合、_x->0_としての制限は、プラスまたはマイナスの無限大であるか、未定義です。 g(x)が_x==0_の近傍で両方の符号をとる場合、制限は定義されていません(左右の制限が一致しません)。ただし、g(x)の符号が0の近くにある場合、制限は定義され、正または負の無限大になります。これについては後で詳しく説明します。
  2. f(0) == 0の場合も、制限は、正の無限大、負の無限大、有限数、または未定義を含む任意の値にすることができます。

2番目のケースでは、一般的に言えば、何も言えません。間違いなく、2番目のケースではNaNが唯一の実行可能な答えです。

さて、最初のケースでは、可能であるか、定義されていない可能性があるのに、なぜ1つの特定の記号を選択するのですか?実際問題として、分母の符号について何か知っている場合は柔軟性が高く、知らない場合は比較的少ないコストで済みます。たとえば、すべてのxに対してg(x) >= 0が分析的にわかっている式、たとえばg(x) = x*xがある場合があります。その場合、制限が定義され、f(0)の符号に等しい符号を持つ無限大になります。コードの便宜のためにそれを利用したいかもしれません。 gの符号について何も知らない他の場合、通常はそれを利用できませんが、ここでのコストは、いくつかの追加のケース(正と負)をトラップする必要があるだけです。無限大-コードを完全にエラーチェックしたい場合は、NaNに加えて。そこにはいくらかの価格がありますが、他の場合に得られる柔軟性と比較して大きくはありません。

質問が「単純な除算」についてだったのに、なぜ一般的な機能について心配するのですか?一般的な理由の1つは、分子と分母を他の算術演算で計算している場合、丸め誤差が累積されることです。これらのエラーの存在は、上記の一般式形式に抽象化できます。たとえば、f(x) = x + e、ここでxは分析的に正しい正確な答え、eは四捨五入によるエラー、f(x)は浮動小数点です。実行時にマシン上に実際にあるポイント番号。

0
Brick