次のスニペットでそれはどうしてですか
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
予想どおり、2.3333ではなく2の値になります。a
とが2倍の場合b
、答えは2.333になります。しかし、確かにc
すでにdoubleであるため、整数で機能するはずでしたか?
では、どうしてint/int=double
うまくいかないのですか?
次のスニペットでそれはどうしてですか
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
予想どおり、2.3333ではなく2の値になります。a
とが2倍の場合b
、答えは2.333になります。しかし、確かにc
すでにdoubleであるため、整数で機能するはずでしたか?
では、どうしてint/int=double
うまくいかないのですか?
これは、 の整数除算バージョンを使用しているためです。operator/
これは 2int
秒かかり、 を返しますint
。double
a を返すバージョンを使用するにはdouble
、少なくとも 1 つの をint
明示的に a にキャストする必要がありますdouble
。
c = a/(double)b;
ここにあります:
a) 2 つint
の s を除算すると、常に整数除算が実行されます。したがって、a/b
あなたの場合の結果はint
.
a
とb
をs として保持したいがint
、それらを完全に分割したい場合は、それらの少なくとも 1 つを double:(double)a/b
またはa/(double)b
またはにキャストする必要があります(double)a/(double)b
。
b)c
は aであるため、代入時に値を受け入れるdouble
ことができます:は自動的に に変換され、 に代入されます。int
int
double
c
c) 代入では、 の右側の式が最初に (上記の規則 (a) に従って、 の左側の変数に関係なく)=
計算され、(に従って( の左側の変数に関係なく)の左側の変数に割り当てられることを思い出してください。 b) 上記)。これで絵が完成すると思います。=
=
ごくわずかな例外を除いて (1 つしか思いつきません)、C++ は式自体から式 (または部分式) の意味全体を判断します。式の結果をどうするかは問題ではありません。あなたの場合、式には見えa / b
ません。double
すべてですint
。したがって、コンパイラは整数除算を使用します。結果が得られると、それをどう処理するかを検討し、それを に変換しdouble
ます。
2 つの整数を除算すると、double に格納するという事実に関係なく、結果は整数になります。
c
はdouble
変数ですが、それに代入されるint
値は 2 つの の除算の結果であり、int
「整数除算」(剰余を削除) した結果であるため、値です。したがって、行で何が起こるかc=a/b
は
a/b
評価され、タイプの一時を作成しますint
c
type への変換後に一時的な値が代入されdouble
ます。の値はa/b
、そのコンテキストを参照せずに決定されます ( への代入double
)。
C++ 言語では、部分式の結果が周囲のコンテキストの影響を受けることはありません (いくつかのまれな例外を除きます)。これは、言語が注意深く従う原則の 1 つです。式c = a / b
には独立した部分式が含まれており、a / b
その部分式の外側にあるものとは独立して解釈されます。言語は、後で結果を に代入することを気にしませんdouble
。a / b
整数除算です。それ以外は問題ありません。言語仕様の多くの部分で、この原則が守られていることがわかります。それがC++(およびC)の仕組みです。
上記の例外の 1 つの例は、関数のオーバーロードを伴う状況での関数ポインターの割り当て/初期化です。
void foo(int);
void foo(double);
void (*p)(double) = &foo; // automatically selects `foo(fouble)`
これは、割り当て/初期化の左側が右側の動作に影響を与えるコンテキストの 1 つです。(また、配列への参照の初期化により、同様の動作の別の例である配列型の減衰が防止されます。) 他のすべての場合、右側は左側を完全に無視します。
この/
演算子は、整数除算または浮動小数点除算に使用できます。2 つの整数オペランドを指定しているため、整数除算を行ってから、結果を double に格納しています。
これは技術的には言語に依存しますが、ほとんどすべての言語がこの主題を同じように扱います。式の 2 つのデータ型の間に型の不一致がある場合、ほとんどの言語は=
、一連の事前定義された規則に従って、一方の側のデータをキャストして他方の側のデータと一致させようとします。
同じ型 (integer、double など) の 2 つの数値を除算すると、結果は常に同じ型になります (したがって、'int/int' は常に int になります)。
この場合
、計算後にdouble var = integer result
整数の結果を double にキャストします。この場合、小数データは既に失われています。(ほとんどの言語は、例外やエラーを発生させずに型の不正確さを防ぐためにこのキャストを行います)。
結果を double として保持したい場合は、次のような状況を作成する必要があります。
double var = double result
これを行う最も簡単な方法は、式の右辺の式を強制的に double にキャストすることです。
c = a/(double)b
integer と double の間の除算は、integer を double にキャストする結果になります (計算を行う場合、コンパイラは、データの損失を防ぐために、最も具体的なデータ型に「アップキャスト」することが多いことに注意してください)。
アップキャストの後、a
ダブルとして巻き上げられ、2 つのダブルの間で分割されます。これにより、目的の分割と割り当てが作成されます。
繰り返しますが、これは言語固有 (コンパイラ固有の場合もあります) であることに注意してください。ただし、ほとんどすべての言語 (確かに、私が頭のてっぺんから思いつくすべての言語) は、この例を同じように扱います。