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