web-dev-qa-db-ja.com

doubleに割り当てられたときに2つのintを除算すると正しい値が得られないのはなぜですか?

どうして次のスニペットで

int a = 7;
int b = 3;
double c = 0;
c = a / b;

cは、期待どおり2.3333ではなく、値2になります。 abが2倍の場合、答えは2.333になります。しかし、確かにcはすでにdoubleであるため、整数で動作するはずです。

では、どうしてint/int=doubleが機能しないのでしょうか?

90
Jahoe

これは、2つのintsを取り、intを返すoperator/の整数除算バージョンを使用しているためです。 doubleを返すdoubleバージョンを使用するには、少なくとも1つのintsを明示的にdoubleにキャストする必要があります。

c = a/(double)b;
144
Chad La Guardia

ここにあります:

a)2つのintsを除算すると、常に整数除算が実行されます。したがって、あなたの場合のa/bの結果はintにしかなれません。

abintsのままにして、それらを完全に分割する場合は、少なくともそのうちの1つを(double)a/bまたはa/(double)bまたは(double)a/(double)bにキャストする必要があります。

b)cdoubleであるため、accept割り当て時のint値:intは自動的にdoubleに変換され、cに割り当てられます。

c)割り当て時に、=の右側の式が計算されることを思い出してくださいfirst(上記の規則(a)に従って、=の左側の変数に関係なく)およびthen=の左側の変数に割り当てられます(上記(b)による)。これで状況が完成すると思います。

11
nplatis

ごくわずかな例外(1つしか考えられない)を除いて、C++は式(またはサブ式)の意味全体を式自体から決定します。式の結果で何をするかは問題ではありません。あなたの場合、式a / bには、doubleが見えません。すべてがintです。そのため、コンパイラは整数除算を使用します。結果が得られたら、それをどう処理するかを検討し、doubleに変換します。

9
James Kanze

2つの整数を除算すると、doubleに格納するという事実に関係なく、結果は整数になります。

6
Alok Save

cdouble変数ですが、それに割り当てられる値はint値です。これは、2つのintsの除算の結果であるため、「整数除算」(剰余の切り捨て)が可能です。行c=a/bで何が起こるかは

  1. a/bが評価され、タイプintの一時ファイルが作成されます
  2. タイプcへの変換後、一時変数の値はdoubleに割り当てられます。

a/bの値は、そのコンテキストを参照せずに決定されます(doubleへの割り当て)。

5
Fred Foo

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つのコンテキストです。 (また、配列への参照の初期化は、同様の動作の別の例である配列型の減衰を防ぎます。)他のすべての場合、右側は左側を完全に無視します。

4
AnT

/演算子は、整数除算または浮動小数点除算に使用できます。あなたはそれに2つの整数オペランドを与えているので、整数除算を行っており、結果はdoubleに格納されています。

4
Vicky

これは技術的には言語に依存しますが、ほとんどすべての言語はこの主題を同じように扱います。式の2つのデータ型に型の不一致がある場合、ほとんどの言語は、事前定義された一連の規則に従って、=の片側でデータをキャストし、反対側のデータと一致させようとします。

同じ型の2つの数値(整数、倍精度など)を除算すると、結果は常に同じ型になります(したがって、「int/int」は常にintになります)。

この場合、double var = integer resultがあり、計算後に整数の結果をdoubleにキャストします。この場合、小数データはすでに失われています。 (ほとんどの言語は、例外やエラーを発生させることなく型の不正確さを防ぐためにこのキャストを行います)。

結果を2倍に保ちたい場合は、double var = double resultがある状況を作りたいと思うでしょう。

最も簡単な方法は、方程式の右側の式を強制的にdoubleにキャストすることです。

c = a/(double)b

整数と倍精度の除算の結果、整数が倍精度にキャストされます(数学を実行する場合、コンパイラは多くの場合、データの損失を防ぐために最も具体的なデータ型に「アップキャスト」します)。

アップキャスト後、aはダブルになり、2つのダブルに分割されます。これにより、目的の部門と割り当てが作成されます。

AGAIN、これは言語固有のものであり(さらにコンパイラ固有のものもあります)、ほとんどすべての言語(確かに私の頭の中で思いつくすべての言語)がこの例を同じように扱っていることに注意してください。

2
matthewdunnam