Can anyone confirm if this is true?
Java will turn a long
% int
into 开发者_如何学Goa long
value. However it can never be greater than the modulus to it is always safe to cast it to an int
.
long a =
int b =
int c = (int) (a % b); // cast is always safe.
Similarly a long
% short
will always be safe to cast to a short
.
If true, does any one know why Java has a longer type for %
than needed?
Additionally, there is a similar case for long
& int
(if you ignore sign extension)
For most (if not all) arithmetic operations, Java will assume you want the maximum defined precision. Imagine if you did this:
long a = ...;
int b = ...;
long c = a % b + Integer.MAX_VALUE;
If Java automatically down-casted a % b
to an int
, then the above code would cause an int
overflow rather than setting c
to a perfectly reasonable long
value.
This is the same reason that performing operations with a double
and an int
will produce a double
. It's much safer to up-cast the least-accurate value to a more accurate one. Then if the programmer knows more than the compiler and wants to down-cast, he can do it explicitly.
Update
Also, after thinking more about this, I'm guessing most CPU architectures don't have operations that combine 32-bit and 64-bit values. So the 32-bit value would need to be promoted to a 64-bit value just to use it as an argument to the CPU's mod operation, and the result of that operation would be a 64-bit value natively. A down-cast to an int
would add an operation, which has performance implications. Combining that fact with the idea that you might actually want to keep a long
value for other operations (as I mention above), it really wouldn't make sense to force the result into an int
unless the developer explicitly wants it to be one.
It is always safe! (Math agrees with me.)
The result of a mod operation is always less than the divisor. Since the result of a mod operation is essentially the remainder after performing integer division, you will never have a remainder larger than the divisor.
I suspect the reason for having the operation return a long
is because the divisor gets expanded to a long
before the operation takes place. This makes a long
result possible. (note even though the variable is expanded in memory, its value will not change. An expanded int
will never be larger than an int
can hold.)
As Marc B alluded to, Java will promote b
to a long
before actually doing the %
operation. This promotion applies to all the arithmetic operations, even <<
and >>
I believe.
In other words, if you have a binary operation and the two arguments don't have the same type, the smaller one will be promoted so that both sides will have the same type.
This is a late party chime-in but the reason is pretty simple:
The bytecode operands do need explicit casts (L2I
) and longs need 2 stack positions compared to 1 for int, char, short, byte [casting from byte to int doesn't need a bytecode instruction]. After the mod operation the result takes 2 positions on the top of stack.
edit: Also, I forgot to mention Java doesn't have division/remainder of 64b/32b. There are only 64->64bit operations, i.e. LDIV
and LREM
.
does any one know why Java has a longer type for % than needed?
I don't know for sure. Maybe to make it work exactly the same way as the other multiplicative operators: *
and \
. In the JLS The type of a multiplicative expression is the promoted type of its operands.
Adding an exception to long % int
would be confusing.
精彩评论