Будет ли длинный% int всегда вписываться в int

Может ли кто-нибудь подтвердить, верно ли это?

Java превратит long% int в значение long. Однако он никогда не может быть больше, чем модуль, поэтому всегда безопасно применять его к int.

long a = 
int b =
int c = (int) (a % b); // cast is always safe.

Аналогично, a long% short всегда будет безопасным для добавления в short.

Если true, знает ли кто-нибудь, почему Java имеет более длинный тип для %, чем нужно?

Кроме того, есть аналогичный случай для long и int (если вы игнорируете расширение знака)

Ответ 1

Для большинства (если не всех) арифметических операций Java предполагает, что вы хотите получить максимальную определенную точность. Представьте, если вы это сделали:

long a = ...;
int b = ...;

long c = a % b + Integer.MAX_VALUE;

Если Java автоматически сбрасывает a % b в int, то приведенный выше код приведет к переполнению int, а не настройке c к вполне разумному значению long.

Это по той же причине, что выполнение операций с double и int приведет к созданию double. Гораздо безопаснее поднимать наименее точное значение до более точного. Тогда, если программист знает больше, чем компилятор, и хочет сбрасывать, он может сделать это явно.

Ответ 2

Это всегда безопасно! (Матх согласен со мной.)

Результат операции mod всегда меньше делителя. Поскольку результат операции mod по существу является остатком после выполнения целочисленного деления, у вас никогда не будет остатка, большего, чем divisor.

Я подозреваю, что причина возврата операции long заключается в том, что до начала операции делитель расширяется до long. Это дает результат long. (обратите внимание, хотя переменная расширена в памяти, ее значение не изменится. Расширение int никогда не будет больше, чем int может удерживать.)

Ответ 3

Как указано в Marc B, Java будет продвигать b до long, прежде чем выполнять операцию %. Эта акция распространяется на все арифметические операции, даже << и >> Я считаю.

Другими словами, если у вас есть двоичная операция, и два аргумента не имеют одного и того же типа, тем меньше будет повышаться, так что обе стороны будут иметь один и тот же тип.

Ответ 4

Это поздняя вечеринка, но причина довольно проста:

Для операндов байткода нужны явные приведения (L2I), а longs - 2 позиции стека по сравнению с 1 для int, char, short, byte [отбрасывание от байта до int не требует инструкции байткода]. После операции mod результат занимает 2 позиции в верхней части стека.

edit: Кроме того, я забыл упомянуть, что Java не имеет деления/остатка 64b/32b. Есть только 64- > 64-битные операции, т.е. LDIV и LREM.

Ответ 5

Кто-нибудь знает, почему Java имеет более длинный тип для%, чем нужно?

Я не знаю точно. Возможно, он работает точно так же, как и другие мультипликативные операторы: * и \. В JLS The type of a multiplicative expression is the promoted type of its operands. Добавление исключения в long % int будет путать.