web-dev-qa-db-ja.com

コンピューターはゼロで除算しようとしますか?

私たちは皆知っています0/0Undefinedであり、電卓に入れようとすると、エラーを返します。プログラムを作成すると(少なくともCで)、ゼロで除算しようとすると、OSによってプログラムが終了します。

しかし、私が不思議に思っているのは、コンピュータがゼロで除算しようとしてもであるか、または「保護機能が組み込まれている」だけなのか、つまり、「見る」ときに0/0計算を試みる前でもエラーを返しますか?

59
Ankush

CPUには検出機能が組み込まれています。ほとんどの命令セットアーキテクチャは、CPUがゼロによる整数除算の例外ハンドラーにトラップすることを指定しています(被除数がゼロかどうかは気にしません)。

除数をゼロにするためのチェックが除算を行う試みと並行してハードウェアで並行して発生する可能性がありますが、問題のある条件の検出は除算とトラップを効果的にキャンセルするので、一部の部分を実際に知ることはできませんそれの分割を試みたかどうか。

(ハードウェアは多くの場合、そのように機能し、複数のことを並行して実行し、その後適切な結果を選択します。これは、適切な操作の選択をシリアル化する代わりに、各操作をすべてすぐに開始できるためです。)

例外メカニズムへの同じトラップは、オーバーフロー検出がオンになっている場合にも使用されます。これは通常、異なるadd/sub/mul命令(またはこれらの命令のフラグ)を使用して要求します。

浮動小数点除算もゼロ除算の組み込み検出機能を備えていますが、例外ハンドラーにトラップする代わりに、異なる値( IEEE 754NaN を指定)を返します。


仮説的に言えば、CPUがゼロで除算する試みの検出を省略した場合、問題には以下が含まれる可能性があります。

  • cPUの停止(たとえば、INFループ内)—これは、CPUが分子を除算するアルゴリズムを使用して分子が(絶対値で)除数よりも小さいときに停止する場合に発生する可能性があります。このようなハングは、CPUのクラッシュと見なされます。
  • cPUがカウンターを使用して最大可能な分割ステップ数(32ビットマシンでは31または32など)で分割を終了する場合、(おそらく予測可能な)ガベージアンサー。
74
Erik Eidt

言語、コンパイラ、整数と浮動小数点数のどちらを使用しているかによって異なります。

浮動小数点数の場合、ほとんどの実装は IEEE 754 標準を使用します。0による除算は明確に定義されています。 0/0は NaN (非数)の明確な結果を与え、x 0 0のx/0はxの符号に応じて+ Infinityまたは-Infinityを与えます。

C、C++などの言語では、ゼロによる除算は未定義の動作を引き起こします。したがって、言語の定義によれば、何かが発生する可能性があります。特にあなたが起こりたくないこと。あなたがコードを書いたときにすべてが完全にうまく機能し、顧客がそれを使用したときにデータを破壊するように。言語の観点から、これをしないでください。一部の言語アプリケーションがクラッシュすることの保証。これがどのように実装されるかは彼ら次第です。これらの言語では、ゼロによる除算はクラッシュします。

多くのプロセッサには、組み込みの「除算」命令があり、プロセッサによって動作が異なります。 Intel 32ビットおよび64ビットプロセッサでは、ゼロで除算しようとすると、「除算」命令によりアプリケーションがクラッシュします。他のプロセッサは異なる動作をする場合があります。

コンパイラーが、コードの実行時にゼロによる除算が発生することを検出し、そのコンパイラーがユーザーにとって適切である場合、警告が表示され、組み込みの「除算」命令が生成されるため、動作は同じ。

34
gnasher729

誰かが除算する前にゼロを明示的にチェックしないCPUを作成した場合、どうなるのかと思っているようです。何が起こるかは、部門の実装に完全に依存します。詳細については説明しませんが、1種類の実装では、すべてのビットが設定された結果が生成されます。 16ビットCPUでは65535。別の人が電話を切るかもしれません。

13
Bingo

しかし、私が不思議に思っているのは、コンピューターがゼロで除算しようとするのか、それとも「組み込みの保護」を備えているのか、それが0/0を「見た」とき、それを計算しようとする前でもエラーを返すのか?

_x/0_は意味をなさないので、ピリオド、コンピューターは常にゼロによる除算をチェックする必要があります。ここに問題があります:プログラマーは、その計算が意味があるかどうかを確認するためにわざわざ煩わすことなく_(a+b)/c_を計算したいと考えています。 CPU +数値タイプ+オペレーティングシステム+言語によるゼロ除算の裏側の反応は、かなり劇的なこと(たとえば、プログラムをクラッシュさせること)または過度に無害なこと(たとえば、何もしない値を作成すること)です。 IEEE浮動小数点NaN、「Not a Number」である数値などの意味)。

通常の設定では、プログラマは_(a+b)/c_が意味をなすかどうかを知っている必要があります。このコンテキストでは、ゼロによる除算をチェックする理由はありません。ゼロによる除算が発生し、マシン言語+実装言語+データ型+オペレーティングシステムの応答がプログラムをクラッシュさせる場合は、問題ありません。応答が、プログラム内のすべての数値を最終的に汚染する可能性がある値を作成することである場合も、それで問題ありません。

高信頼性コンピューティングの世界では、「思い切ったもの」も「過度に無害」も正しいことではありません。これらのデフォルトの応答は、患者を殺したり、旅客機を墜落させたり、爆弾を間違った場所で爆発させたりする可能性があります。信頼性の高い環境では、_(a+b)/c_を作成するプログラマーはコードレビュー中に死ぬか、または現代では、多発した構造をチェックするツールによって自動的に死ぬかもしれません。この環境では、そのプログラマは代わりにdiv(add(a,b),c)の行に沿って何かを記述している必要があります(そしておそらくエラーステータスのいくつかのチェック)。内部で、div(およびadd)関数/マクロは、ゼロによる除算(またはaddの場合はオーバーフロー)から保護します。その保護に伴うものは、非常に実装固有です。

1
David Hammen