Будет ли длинный% 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
будет путать.