私はしばらく C++ でプログラミングを行っていましたが、突然疑問が生じ、Stackoverflow コミュニティで明確にしたいと思いました。
整数を別の整数で割ると、結果が整数であることがわかります。同様に、float で割った float も float です。
しかし、この結果を提供する責任は誰にあるのでしょうか? コンパイラですか、それとも DIV 命令ですか。
私はしばらく C++ でプログラミングを行っていましたが、突然疑問が生じ、Stackoverflow コミュニティで明確にしたいと思いました。
整数を別の整数で割ると、結果が整数であることがわかります。同様に、float で割った float も float です。
しかし、この結果を提供する責任は誰にあるのでしょうか? コンパイラですか、それとも DIV 命令ですか。
それは、アーキテクチャにDIV
命令があるかどうかによって異なります。アーキテクチャに整数除算命令と浮動小数点除算命令の両方がある場合、コンパイラは、コードで指定された場合に適切な命令を発行します。言語標準では、型昇格の規則と、考えられる状況ごとに整数除算と浮動小数点除算のどちらを使用するかが指定されています。
整数除算命令のみ、または浮動小数点除算命令のみがある場合、コンパイラは一部のコードをインライン化するか、除算を処理するために数学サポート ライブラリへの呼び出しを生成します。除算命令は非常に遅いことで知られているため、ほとんどのコンパイラは、可能であればそれらを最適化しようとします (たとえば、シフト命令に置き換えるか、コンパイル時の定数の除算の結果を事前に計算します)。
コンパイラは、コンパイル時に、使用されている変数の型に基づいて、必要な除算の形式を決定します。1 日の終わりに、何らかの形式の DIV (または FDIV) 命令が関与します。
ハードウェア除算命令には、整数と浮動小数点の間の変換が含まれることはほとんどありません。除算命令が出たとしても(除算回路が大きくて複雑なため省略されることもあります)、「int を int で割って int を生成」「float を float で割って float を生成」であることがほぼ確実です。 . また、通常、入力と出力の両方もすべて同じサイズです。
コンパイラは、これらのプリミティブの上に、ソース コードに記述された操作を構築する責任があります。たとえば、C で float を int で除算すると、コンパイラは int から float への変換を発行し、次に float 除算を発行します。
(奇抜な例外は存在します。わかりませんが、「整数による浮動小数点数の除算」タイプの命令を VAX より先に置くことはしませんでした。Itanium には実際には除算命令はありませんでしたが、その「除算ヘルパー" は浮動小数点専用で、浮動小数点除算の上に整数除算を偽造する必要がありました!)
あなたの質問は本当に意味がありません。DIV 命令自体は何もしません。いくら怒鳴っても賄賂を渡そうとしても何の責任も負わない
プログラミング言語 [X] でプログラミングする場合、[X] コンパイラは、ソース コードで記述したことを実行するプログラムを作成する責任があります。
除算が要求された場合、コンパイラは除算を行う方法を決定します。これは、対象の CPU にオペコードがある場合、命令のオペコードを生成することで発生する可能性がありDIV
ます。コンパイル時に除算を事前に計算し、その結果をプログラムに直接挿入する (両方のオペランドがコンパイル時に既知であると仮定) か、除算を一緒にエミュレートする一連の命令を生成することによって行われる可能性があります。
しかし、それは常にコンパイラ次第です。C++ 標準に従って解釈されない限り、C++ プログラムは効果がありません。プレーン テキスト ファイルとして解釈しても、何もしません。コンパイラがそれを Java プログラムとして解釈すると、チョークして拒否します。
また、DIV 命令は C++ 標準について何も知りません。一方、C++ コンパイラは、C++ 標準を理解し、それに従ってコードを変換することのみを目的として作成されています。
コンパイラは常に責任を負います。
C ++標準で最も重要なルールの1つは、「あたかも」ルールです。
この国際規格のセマンティック記述は、パラメーター化された非決定論的抽象マシンを定義します。この国際規格は、適合実装の構造に要件を課していません。特に、抽象マシンの構造をコピーしたりエミュレートしたりする必要はありません。むしろ、以下で説明するように、抽象マシンの観察可能な動作を(のみ)エミュレートするには、準拠する実装が必要です。
あなたの質問に関連して、それが行われる限り、どのコンポーネントが分割を行うかは問題ではないことを意味します。問題のプロセッサに適切な命令がない場合は、DIV
マシンコードによって実行される場合もあれば、より複雑なコードによって実行される場合もあります。
また、次のこともできます。
C99 標準では、「整数を除算すると、/ 演算子の結果は小数部分が破棄された代数商になる」と定義されています。そして脚注に、「これはしばしば『ゼロへの切り捨て』と呼ばれる」と付け加えています。
歴史的に、言語仕様が責任を負います。
Pascalでは、 for 除算を使用すると (2 つの整数を除算する場合でも) 常に a が返されるように演算子が定義されており、整数を除算して整数の結果を得たい場合は、代わりに演算子を使用します。(Visual Basic にも同様の区別があり、整数の結果を返す整数除算に演算子を使用します。)/
real
div
\
float
C では、浮動小数点の結果が必要な場合は、整数オペランドの 1 つを a にキャストすることによって、同じ区別を行う必要があると判断されました。多くの C 派生言語で記述されているように、整数型と浮動小数点型を扱うのが慣例になっています。この規則は Fortran に由来するのではないかと思います。