开发者

Why does dividing two int not yield the right value when assigned to double?

How come that in the following snippet

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

c ends up having the value 2, rather than 2.3333, as one would expect. If a and b are doubles, the answer does turn to 2.333. But surely because c already 开发者_高级运维is a double it should have worked with integers?

So how come int/int=double doesn't work?


This is because you are using the integer division version of operator/, which takes 2 ints and returns an int. In order to use the double version, which returns a double, at least one of the ints must be explicitly casted to a double.

c = a/(double)b;


Here it is:

a) Dividing two ints performs integer division always. So the result of a/b in your case can only be an int.

If you want to keep a and b as ints, yet divide them fully, you must cast at least one of them to double: (double)a/b or a/(double)b or (double)a/(double)b.

b) c is a double, so it can accept an int value on assignement: the int is automatically converted to double and assigned to c.

c) Remember that on assignement, the expression to the right of = is computed first (according to rule (a) above, and without regard of the variable to the left of =) and then assigned to the variable to the left of = (according to (b) above). I believe this completes the picture.


With very few exceptions (I can only think of one), C++ determines the entire meaning of an expression (or sub-expression) from the expression itself. What you do with the results of the expression doesn't matter. In your case, in the expression a / b, there's not a double in sight; everything is int. So the compiler uses integer division. Only once it has the result does it consider what to do with it, and convert it to double.


When you divide two integers, the result will be an integer, irrespective of the fact that you store it in a double.


c is a double variable, but the value being assigned to it is an int value because it results from the division of two ints, which gives you "integer division" (dropping the remainder). So what happens in the line c=a/b is

  1. a/b is evaluated, creating a temporary of type int
  2. the value of the temporary is assigned to c after conversion to type double.

The value of a/b is determined without reference to its context (assignment to double).


In C++ language the result of the subexpresison is never affected by the surrounding context (with some rare exceptions). This is one of the principles that the language carefully follows. The expression c = a / b contains of an independent subexpression a / b, which is interpreted independently from anything outside that subexpression. The language does not care that you later will assign the result to a double. a / b is an integer division. Anything else does not matter. You will see this principle followed in many corners of the language specification. That's juts how C++ (and C) works.

One example of an exception I mentioned above is the function pointer assignment/initialization in situations with function overloading

void foo(int);
void foo(double);

void (*p)(double) = &foo; // automatically selects `foo(fouble)`

This is one context where the left-hand side of an assignment/initialization affects the behavior of the right-hand side. (Also, reference-to-array initialization prevents array type decay, which is another example of similar behavior.) In all other cases the right-hand side completely ignores the left-hand side.


The / operator can be used for integer division or floating point division. You're giving it two integer operands, so it's doing integer division and then the result is being stored in a double.


This is technically a language-dependent, but almost all languages treat this subject the same. When there is a type mismatch between two data types in an expression, most languages will try to cast the data on one side of the = to match the data on the other side according to a set of predefined rules.

When dividing two numbers of the same type (integers, doubles, etc.) the result will always be of the same type (so 'int/int' will always result in int).

In this case you have double var = integer result which casts the integer result to a double after the calculation in which case the fractional data is already lost. (most languages will do this casting to prevent type inaccuracies without raising an exception or error).

If you'd like to keep the result as a double you're going to want to create a situation where you have double var = double result

The easiest way to do that is to force the expression on the right side of an equation to cast to double:

c = a/(double)b

Division between an integer and a double will result in casting the integer to the double (note that when doing maths, the compiler will often "upcast" to the most specific data type this is to prevent data loss).

After the upcast, a will wind up as a double and now you have division between two doubles. This will create the desired division and assignment.

AGAIN, please note that this is language specific (and can even be compiler specific), however almost all languages (certainly all the ones I can think of off the top of my head) treat this example identically.


For the same reasons above, you'll have to convert one of 'a' or 'b' to a double type. Another way of doing it is to use:

double c = (a+0.0)/b;

The numerator is (implicitly) converted to a double because we have added a double to it, namely 0.0.


The important thing is one of the elements of calculation be a float-double type. Then to get a double result you need to cast this element like shown below:

c = static_cast<double>(a) / b;

or c = a / static_cast(b);

Or you can create it directly::

c = 7.0 / 3;

Note that one of elements of calculation must have the '.0' to indicate a division of a float-double type by an integer. Otherwise, despite the c variable be a double, the result will be zero too (an integer).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜