I\'m a beginner and there\'s something that\'s not making much sense to me. Please could be so kind as to explain where I\'m going wrong. I\'m sorry if this has been asked b
This is specified in the Java Language Specification - Numeric Promotions
If any of the operands is of a reference type, unboxing conversion (§5.1.8) is performed.
Then:
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
The concept is called widening conversion:
5.1.2 Widening Primitive Conversion
The following 19 specific conversions on primitive types are called the widening primitive conversions:
- byte to short, int, long, float, or double
- short to int, long, float, or double
- char to int, long, float, or double
- int to long, float, or double
- long to float or double float to double
The reason why
(int) (1.0/3) == 0
is because you cast the result of 1.0/3 (0.33333... by the above rules) explicitly to an integer, which is equivalent to "floor(result)" (rounding down), so the result is 0.
Cast has a higher precedence than /, that's why the other operations were misleading to your understanding:
(double) 1 / 3
will explicitly cast 1 to a double value 1.0 first, so again the result by the above rules is equal to 0.3333....
There are two factors in all those cases:
I'll give three examples from your question:
(double) (1/3)
- first evaluate the expression in parenthesis - (1/3) is an integer division so the result is 0
, then cast it to double, you get 0.0
(int) (1.0/3)
- first evaluate the expression in parenthesis - (1.0/3) is a floating point division, so the result is 0.3333
, then cast it to int, and you get 0
(double)1
becomes 1.0, then evaluate the division 1.0/3
- this is a floating point division, so the result is 0.3333
Java's language parsing rules are basically implying a lot of parentheses everywhere in your code based on its rules of order of operations. Understanding where Java thinks the parentheses are will help you understand this behavior. When you say:
(double) 1 / 3.0
... this is equivalent to saying:
((double) 1) / 3.0
This means that 1 gets converted to a double, and 3.0 is automatically a double, so you'll end up doing a floating point division rather than integer division. The same thing would happen with (double) 1 / 3
, because the divisor is a double
, so even though the dividend is an int
, the system realizes that you want to do floating-point division. The compiler doesn't want you to lose precision unless you specifically ask to, so any time either the dividend or the divisor is a double
, it will do double
division.
On the other hand:
(int) 1 / 3.0
... is the same as saying:
((int) 1) / 3.0
In this case, you're telling the compiler what it already knew: that the divisor (1) is an int
. Then you're asking it to divide by a double
value (3.0). Since the dividend is a double
, it will perform double
division.
As you noted, 1/3
will produce zero, because that's how integer division works and both numbers are integers. The same will happen with 1/(int)3.0
because you're telling the compiler to make the 3.0
into an int
before the division will occur (as in 1/((int)3.0)
).
The final point to keep in mind is that (int) 0.33
will also get converted to 0
, because an integer can't hold decimal values in it. So when you say (int)(1.0/3)
, you're doing double
division, but then you're converting the double into an int
afterwards, producing 0
.
The cast is only applied to the expression immediately after it.
Examples:
(int)1/3
applies the cast to the 1. equivalent to ((int)1)/3
(int)(1/3)
the cast is applied to the result of the expression.
(int)((double)1.333*(float)3.167)
getting a little more complicated. 1.333 casted to double,
multiplied by 3.167 casted to a float, with the result casted to an int
Hope that helps!