Я уже однажды расписывал операции в Java. В этой статье я акцентрирую внимание на операцию взятия остатка от деления, так как её работа отличается в различных языках программирования и иногда порождает недопонимание.
Операция взятия остатка % в Java работает не только с целыми числами, но и с числами с плавающей точкой.
Для целых чисел операция взятия остатка работает по такому принципу, что результат операции будет таким, что будет выполняться равенство:
1 |
(a / b) * b + (a % b) == a |
Это равенство действует даже в том случае, если левый операнд будет наименьшим отрицательным числом для своего типа, а операнд в правой части будет равен -1 (тогда результатом будет 0).
Результатом операции взятия остатка для целых чисел в Java может быть отрицательное число только в том случае, если левый операнд будет отрицательным числом, а также результат может быть положительным только в том случае, если операнд в левой части будет положительным числом.
Если в правой части операции взятия остатка для целочисленных операндов в Java стоит 0, то результатом будет ArithmeticException.
Примеры работы операции взятия остатка для целочисленных операндов (выполнено в JShell):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
$ ./jshell | Welcome to JShell -- Version 10.0.1 | For an introduction type: /help intro jshell> 5 % 3 $1 ==> 2 jshell> 5 / 3 $2 ==> 1 jshell> 5 % (-3) $3 ==> 2 jshell> 5 / (-3) $4 ==> -1 jshell> (-5) % 3 $5 ==> -2 jshell> (-5) / 3 $6 ==> -1 jshell> (-5) % (-3) $7 ==> -2 jshell> (-5) / (-3) $8 ==> 1 |
Как я уже говорил, в Java операция взятия остатка % работает и с числами с плавающей точкой ( float и double). Согласно спецификации языка Java операция взятия остатка для чисел с плавающей точкой работает не так, как это принято в IEEE 754, но если очень нужно то можно использовать метод Math.IEEEremainder.
В Java операция взятия остатка % работает согласно следующим правилам:
- Если один из операндов равен NaN, то результат операции будет NaN.
- Если результат не NaN, то знаком результата будет знак операнда в левой части.
- Если операнд в левой части Infinity, или операнд в правой части равен нулю, или выполняются оба условия, то результат будет равен операнду в левой части.
- Если операнд в левой части конечен, а операнд в правой части Infinity, то результат будет равен операнду в левой части.
- Если операнд в левой части равен нулю, а операнд в правой части конечен, то результат будет равен операнду в левой части.
- Во всех остальных случаях результат r взятия остатка от операнда n при делении на d определяется по математической формуле r = n — (d × q), где q будет целым числом, которое отрицательно только в случае, если n / d отрицательно, и положительно, если n / d положительно, и его размер максимально возможный, но не превышающий отношение n и d. Пример: 0,5 ÷ 0,3 = 1,6, тогда q будет положительным, так как 1,6 положительно, а наибольший размер, не превышающий 1,6 будет 1, то q = 1, а значит r = 0,5 — (0,3 × 1) = 0,2.
Операция взятия остатка для чисел с плавающей точкой никогда не приводит к возникновению Exception-ов.
Примеры операции взятия остатка для чисел с плавающей точкой:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
$ ./jshell | Welcome to JShell -- Version 10.0.1 | For an introduction type: /help intro jshell> Double.NaN % 3.0 $1 ==> NaN jshell> 5.0 % Double.NaN $2 ==> NaN jshell> Double.NaN % Double.NaN $3 ==> NaN jshell> Double.POSITIVE_INFINITY % 0.0 $4 ==> NaN jshell> 5.0 % Double.POSITIVE_INFINITY $5 ==> 5.0 jshell> 5.0 % Double.NEGATIVE_INFINITY $6 ==> 5.0 jshell> 0.0 % 3.0 $7 ==> 0.0 jshell> -0.0 % 3.0 $8 ==> -0.0 jshell> 5.0 % 3.0 $9 ==> 2.0 jshell> 5.0 % (-3.0) $10 ==> 2.0 jshell> (-5.0) % 3.0 $11 ==> -2.0 jshell> (-5.0) % (-3.0) $12 ==> -2.0 jshell> 5.1 % 3.2 $13 ==> 1.8999999999999995 jshell> -5.12 % 3.4 $14 ==> -1.7200000000000002 |
Имейте в виду, что в других языках операция взятия остатка может работать по-другому. В этой статье описана работа операции взятия остатка % для языка Java.