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


59

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

しかし、私が考えていたのは、コンピューターがゼロ除算しようとするのか、それとも「組み込みの保護」があるだけなのか、それ0/0を計算しようとする前でもエラーを返すのですか?


10
0/0は未定義、他の数字/ 0は異なる種類のエラーです。2つを混同しているようです
-edc65

7
0で割った数は、数学的に言えば未定義です。
マノデストラ

12
@jwg:「値があった場合、1になります」-必ずしもではありません。ある数学の全支店値が異なる状況にあるかもしれないものに専念が:)
psmears

11
ここで用語を明確にするために、0/0 は不定形式と呼ばれ、非ゼロのxの x / 0 はundefinedです。0/0で終わる計算は、実際の答えを出すために異なる方法で計算されることがよくありますが、x / 0は本質的に意味がありません。
時代

9
@jwgでは、ロピタールのルールに興味があるかもしれません。0/0は、1の値を意味するものではありません場合は間違いなくあります
d0nut

回答:


74

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

除数の試みと並行してゼロ除数のチェックがハードウェアで並行して行われる可能性がありますが、問題のある状態の検出により、代わりに除算とトラップが事実上キャンセルされます。その分割を試みたかどうか。

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

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

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


仮に言えば、CPUがゼロ除算の試みの検出を省略した場合、問題には以下が含まれます。

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

51
@Ankush「システムクラッシュ」は、実際にはCPUレベルで発生するものではありません。ゼロ除算でトラップしなかったCPUの最も可能性の高い動作は、単純に除算演算を実行し、ナン​​センスな結果を生成して続行することです。オーバーフローが発生する2つの整数を追加するときと同じです。
Ixrec

6
浮動小数点の場合、「NaN」と「トラップ」の選択は通常、FPUでフラグを反転することで設定可能です。
バティーン

10
@Ankush lxrecが言ったことが不明確だった場合:CPUに関しては、クラッシュのようなものはありません。
user253751

7
@Ankush CPUレベルの「システムクラッシュ」を引き起こす状況はほとんどありません。そのような場合、熱保護シャットダウン(過熱保護)、トリプルフォールトなどの状況について話します。無効なオペコードを含む、通常の使用で発生するほとんどすべてのクラッシュは、何らかの方法でトラップとリカバリを行うか、単にエラーを無視して、クリーンな状態で実行を継続することによって処理されます。
CVn

8
ゼロによる除算をトラップしなかった場合、結果は、プログラミング用語では「未定義の動作」になります。これは、コンピューターが何でもできることを意味します。Bergiが言及しているように、バグのあるループに入り、ハングする可能性があります。単純に除算ロジックの実装に由来する不特定の一連のビットを出力する場合があります(コンピュータは数学的な意味で「除算」しません。除算に十分近い2つの数値で演算を行います。通常、単に「除算」と呼ぶことにします。浮動小数点の丸めも参照してください)。
コートアンモン

34

言語、コンパイラ、整数または浮動小数点数のいずれを使用しているかなどに依存します。

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

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

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

コンパイラーは、コードの実行時にゼロによる除算が発生することをコンパイラーが検出し、コンパイラーがユーザーに良い場合、警告を出し、組み込みの「除算」命令を生成して動作が同じ。


22
「Intel 32ビットおよび64ビットプロセッサでは、ゼロで除算しようとすると、「除算」命令によりアプリケーションがクラッシュします。」引用が必要です。CPUはアプリケーションについて何も考えず、命令を実行し、(MMUを含める場合)メモリアクセス制限を強制します(リング0または非Intel x86アーキテクチャで同等の場合を除く)。命令がアプリケーションBやオペレーティングシステムコンポーネントCではなくアプリケーションAの一部であることは、CPUとは無関係です。命令が命令Xであるか、メモリアドレスYを使用できるかは関係があります。
CVn

1
@MichaelKjörlingのコメントに追加するには:OSには、このアプリケーション(およびその他の種類のエラー)を通知する方法があります。Windowsの世界では、(願わくば)インストールされたStructed Exception Handling Handler によって処理されるEXCEPTION_INT_DIVIDE_BY_ZERO値ですEXCEPTION_RECORD
-user45891

1
アプリがクラッシュすることを保証する以外のことを行うこともあります。たとえば、多くの言語/プラットフォームでは、ゼロ除算で例外がスローされることが保証されています。その後、クラッシュすることなく、上記の例外をキャッチして処理できます。
-reirab

2
「他のプロセッサの動作が異なる可能性があります」内で「may」を削除できます。PowerPCプラットフォームでは、除算の結果はゼロ除算でゼロになります。X86プラットフォームのパニック動作よりもはるかに便利です。
cmaster

13

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


1

しかし、私が疑問に思っているのは、コンピューターがゼロで除算しようとするのか、それとも「組み込みの保護」があるだけなのか、0/0を「見る」ときに計算を試みる前でもエラーを返すということです。

x/0意味のない期間なので、コンピューターは常にゼロによる除算をチェックする必要があります。ここに問題があります:プログラマーは(a+b)/c、その計算が理にかなっているかどうかをわざわざ確認する必要なく計算することを望みます。CPU +数値型+オペレーティングシステム+言語によるゼロ除算に対する内部の応答は、かなり抜本的な処理(プログラムのクラッシュなど)を行うか、過度に良性の処理(例: IEEE浮動小数点などの意味NaN、「Not a Number」)。

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

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


NaNが学校で学んだ算術に従わないからといってそれが意味をなさないというわけではありません。異なる算数に従う
カレス

-2

私たちは今ではそれを知っており、明確な答えはx/0あり0/0ません。0/0とにかく計算しようとするとどうなりますか?

最新のシステムでは、計算はCPU内のMPUに渡され、不正な操作としてフラグが立てられ、を返しNaNます。

オンチップ部門を持たない80年代のホームコンピューターなど、はるかに古いシステムでは、実行中のソフトウェアにかかわらず計算が行われました。いくつかの選択肢があります。

  • 値がゼロになるまで除数のより小さいコピーを減算し、どのサイズのコピーが減算されたかを追跡します
    • 最初の減算の前にゼロをチェックすると、すぐに終了し、結果は 0
    • 少なくとも1回減算できる必要があると仮定した場合、結果は次のようになります。 1
  • 両方の数値の対数を計算し、それらを減算し、eの結果を累乗します。上記の減算方法と比較して非常に非効率的な方法ですが、数学的には有効です
    • 計算しようとしてオーバーフローが発生する可能性がlog(0)あり、ソフトウェアはエラー処理ルーチンを使用するか、クラッシュします
    • ソフトウェアは、すべての対数が一定のステップ数で計算され、大きな値であるが誤った値を返すと想定する場合があります。両方の対数は同じになるため、差は0e 0 = 1となり、次の結果が得られます。1

言い換えれば、何が起こるかは実装に依存し、すべての値に対して正しい予測可能な結果を​​生成するソフトウェアを作成することは可能ですが0/0、それでもなお一見奇妙な値は内部的に一貫しています。


3
この質問は、整数をゼロで除算することに関するものNaNであり、整数のようなものはありません。
デビッドハメン

3
CPUはログを計算し、減算して除算結果を計算しません。対数命令のタイミングは、除算より数桁大きくなります。log(0)の値は何ですか?
ウォリック

1
@DavidHammen OPは一度も整数に言及したことはなく、質問にコメントした人もいませんでした。整数は回答でのみ言及されています。
CJデニス

@wallyk私はすでにその対数はvery inefficient除算のためであると答えました。算術のコストは(加算=減算)<=乗算<=除算です。加算と同じクロックサイクル数(通常は1)で除算できるMPUがない場合、除算は加算と減算よりも高価で、通常は乗算よりも高価です。
CJデニス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.