开发者

Will a long % int will always fit into an int

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.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜