



Вот представление вашего псевдокода в минимальном Java-коде;
boolean isEven = a % 2 == 0;
Теперь я разобью его на составляющие. Оператор модуля в Java - это символ процента (%). Поэтому взятие int% int возвращает другое int. Оператор двойного равенства (==) используется для сравнения значений, таких как пара целых чисел, и возвращает логическое значение. Затем он присваивается логической переменной isEven. В зависимости от приоритета оператора модуль будет оценен перед сравнением.
Оператор по модулю -% (знак процента). Чтобы проверить на равномерность или вообще по модулю для степени 2, вы также можете использовать & (оператор and), например isEven =! (A & 1).
if (a % 2 == 0) {
} else {
}
Вместо оператора по модулю, имеющего немного другую семантику, для неотрицательных целых чисел вы можете использовать оператор остаток%. Для вашего точного примера:
if ((a % 2) == 0)
{
isEven = true;
}
else
{
isEven = false;
}
Это можно упростить до однострочного:
isEven = (a % 2) == 0;
В if / else нет необходимости, просто используйте isEven = (a% 2) == 0,
Будьте осторожны с терминами модульный и модульный, потому что n (mod m) ВСЕГДА> = 0, но не n% m. n% m находится в диапазоне> -m и <m. Хотя в Java есть оператор остатка для типов int и long, в нем нет функции или оператора модуля. То есть -12% 10 = -2, тогда как -12 mod 10 = 8. Если оператор% возвращает отрицательное значение для n% m, тогда (n% m) + m даст вам n mod m. BigInteger предоставляет функции для обоих, и их спецификации хорошо объясняют разницу. Также осторожно с нулем. В математике, хотя ноль является четным числом, он НЕ является положительным или отрицательным.
почему a % 2 заключен в скобки перед оценкой == 0?
@ nl-x Вероятно, потому что лучше явно указать приоритет, чем оставить это на усмотрение. Я, например, не знал, что % оценивается до ==, прежде чем я его искал, поэтому было бы неясно, эквивалентно ли выражение (a%2)==0 или a%(2==0). Я думаю, это менее важно в java, где логическое значение не совпадает с целым числом
Это не оператор модуля - это оператор остатка. Исправьте пожалуйста пост!
логическое даже = ((a & 1) == 0). Намного легче.
Я считаю, что явное if / else проще для глаз и быстрее для сканирования (было бы еще быстрее, если бы открывающие скобки находились в той же строке, что и сигнатуры методов, но, в конце концов, это личное предпочтение). Но мы не всегда должны выбирать «самый короткий», если он снижает удобочитаемость (думая о тернарном вложении операторов).
Также мод можно использовать так:
int a = 7;
b = a % 2;
b будет равен 1. Поскольку 7 % 2 = 1.
вероятно, будет ошибкой использовать составные операторы в примере для начинающих и без вывода.
Альтернатива коду из @Cody:
Используя оператор модуля:
bool isEven = (a % 2) == 0;
Я думаю, что это немного лучший код, чем написание if / else, потому что здесь меньше дублирования и неиспользуемой гибкости. Для изучения требуется немного больше мозгов, но хорошее название isEven компенсирует это.
Это оператор остатка, а не оператор модуля.
@EJP ок. Тогда что такое оператор модуля?
В Java фактически нет оператора по модулю, как в C. % в Java - оператор остатка. Для положительных целых чисел он работает точно так же, как по модулю, но по-другому работает с отрицательными целыми числами и, в отличие от модуля, может работать и с числами с плавающей запятой. Тем не менее, редко можно использовать% для чего-либо, кроме положительных целых чисел, поэтому, если вы хотите называть это модулем, не стесняйтесь!
Но мне нужен настоящий оператор по модулю, который работает и для отрицательных целых чисел, чтобы array[x mod array.length] всегда обращался к элементу в моем массиве, а не пытался индексировать отрицательные позиции.
(x % y + y) % y или начиная с Java 8, Math.floorMod(x, y)
Поскольку все остальные уже дали ответ, я добавлю немного дополнительного контекста. % оператор "модуля" фактически выполняет остальную операцию. Разница между mod и rem тонкая, но важная.
(-1 mod 2) обычно дает 1. Более конкретно, учитывая два целых числа, X и Y, операция (X mod Y) имеет тенденцию возвращать значение в диапазоне [0, Y). Иными словами, модуль X и Y всегда больше или равен нулю и меньше Y.
Выполнение той же операции с оператором «%» или rem сохраняет знак значения X. Если X отрицательно, вы получите результат в диапазоне (-Y, 0]. Если X положительный, вы получите результат в диапазоне [0, Y).
Часто это тонкое различие не имеет значения. Однако, возвращаясь к вопросу о коде, есть несколько способов решения проблемы «равномерности».
Первый подход хорош для новичков, потому что он особенно многословен.
// Option 1: Clearest way for beginners
boolean isEven;
if ((a % 2) == 0)
{
isEven = true
}
else
{
isEven = false
}
Второй подход лучше использует преимущества языка и приводит к более сжатому коду. (Не забывайте, что оператор == возвращает логическое значение.)
// Option 2: Clear, succinct, code
boolean isEven = ((a % 2) == 0);
Третий подход здесь для полноты и использует оператор тройной. Хотя тернарный оператор часто бывает очень полезен, в данном случае я считаю второй подход лучшим.
// Option 3: Ternary operator
boolean isEven = ((a % 2) == 0) ? true : false;
Четвертый и последний подход - использовать знание двоичное представление целых чисел. Если младший бит равен 0, то число четное. Это можно проверить с помощью побитовый оператор и (&). Хотя этот подход является самым быстрым (вы выполняете простую битовую маскировку вместо деления), он, возможно, немного продвинут / сложен для новичка.
// Option 4: Bitwise-and
boolean isEven = ((a & 1) == 0);
Здесь я использовал побитовый оператор и и представил его в сжатой форме, показанной в варианте 2. Переписав его в форме варианта 1 (и, как вариант, варианта 3), мы оставляем читателю в качестве упражнения. ;)
Надеюсь, это поможет.
Спасибо, Роб. Эта путаница вызывает огромные трудности в объяснении программистам, как реализовать алгоритмы с математическими свойствами из модульной арифметики. Остаток НЕ является модулем, но можно быстро получить модуль из остатков.
@TickledPink За исключением того, что это не компилируется в Java.
Чтобы заставить Java-операцию% (REM) работать как MOD для отрицательных значений X и положительных Y, вы можете использовать этот метод:
private int mod(int x, int y)
{
int result = x % y;
if (result < 0)
{
result += y;
}
return result;
}
или с тернарным оператором (короче, но невозможно или менее эффективно в некоторых ситуациях):
private int mod(int x, int y)
{
int result = x % y;
return result < 0? result + y : result;
}
Оператор остатка в Java - %, а оператор по модулю может быть выражен как
public int mod(int i, int j)
{
int rem = i % j;
if (j < 0 && rem > 0)
{
return rem + j;
}
if (j > 0 && rem < 0)
{
return rem + j;
}
return rem;
}
Код работает намного быстрее без использования модуля:
public boolean isEven(int a){
return ( (a & 1) == 0 );
}
public boolean isOdd(int a){
return ( (a & 1) == 1 );
}
Это выглядит намного чище, чем принятый ответ. Это не имеет ничего общего с преждевременной оптимизацией. Просто лучше, - если это сработает.
@LluisMartinez Это одно из самых неправильно цитируемых высказываний в сфере вычислений. Полная цитата такова: «Программисты тратят огромное количество времени на размышления или беспокойство о скорости некритичных частей своих программ, и эти попытки повышения эффективности на самом деле имеют сильное негативное влияние, когда рассматриваются отладка и обслуживание. Мы должны забыть о небольших показатели эффективности говорят о 97% случаев: преждевременная оптимизация - корень всех зол. Тем не менее, мы не должны упускать наши возможности в этих критических 3% ». Что на самом деле означает совсем другое.
@EJP Вы, наверное, правы. Я провел тест (цикл с 1 миллионом итераций) занял 4000 наносекунд с модулем, 2500 наносекунд с логическим и.
Почему это был бы ответ? Конечно, он делает нечетное и четное, но ничего не делает с оператором модификации / остатка. Вопрос касается оператора мода, а не того, как найти четное нечетное.
вам следует изучить спецификацию перед использованием оператора остатка%:
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.17.3
// bad enough implementation of isEven method, for fun. so any worse?
boolean isEven(int num)
{
num %= 10;
if (num == 1)
return false;
else if (num == 0)
return true;
else
return isEven(num + 2);
}
isEven = isEven(a);
Хотя можно сделать правильный модуль, проверив, является ли значение отрицательным, и скорректировать его, если это так (как многие предлагали), существует более компактное решение.
(a % b + b) % b
Сначала выполняется вычисление по модулю, ограничивая значение диапазоном -b -> + b, а затем добавляется b, чтобы гарантировать, что значение положительное, позволяя следующему модулю ограничить его диапазоном 0 -> b.
Примечание: если b отрицательно, результат также будет отрицательным.
Это может вызвать переполнение, если a и b оба являются большими числами, поэтому это неправильное решение.
Другой способ:
boolean isEven = false;
if ((a % 2) == 0)
{
isEven = true;
}
Но самый простой способ:
boolean isEven = (a % 2) == 0;
Как сказал @Steve Kuo.
В Java это оператор %:
15.17.3. Остающийся оператор%
Обратите внимание, что в классе floorMod также есть java.lang.Math, который даст другой результат, чем %, для аргументов с разными знаками:
public static int floorMod(int x, int y)
Проголосовали за, потому что floorMod - лучший оператор «по модулю», чем %, так как он также работает правильно, когда аргумент отрицательный. Ни один из других ответов на самом деле не является правильным, поскольку они содержат отказ от ответственности, что% на самом деле не является модулем, если аргументы не являются положительными. В частности, если вы хотите сопоставить каждое целое число с последовательной позицией в массиве, тогда array[floorMod(i, array.length) работает правильно, даже если индекс i переходит на отрицательную территорию. Не так с %.
В Java операция мод может выполняться как таковая:
Math.floorMod(a, b)
Примечание:
Операция мод отличается от операции остаток. В Java операция остаток может выполняться как таковая:
a % b
Ну, не совсем ... В javadoc Math.floorMod() есть это: The floor modulus is x - (floorDiv(x, y) * y), has the same sign as the divisor y, and is in the range of -abs(y) < r < +abs(y). Так что это не совсем то же самое, что математический модуль. Но, есть способ получить положительный результат, тоже в Javadoc того же метода: If the signs of arguments are unknown and a positive modulus is needed it can be computed as (floorMod(x, y) + abs(y)) % abs(y).
@WesternGun Это может быть правдой, но если вы знаете, что модуль положительный, тогда операция floorMod работает должным образом. Существует также floorMod для значений long и BigInteger для более высоких значений.
Как указывали другие, оператор % (остаток) не совпадает с математическим
Операция / функция модуля mod.
modvs%The
x mod nfunction mapsxtonin the range of[0,n).
Whereas thex % noperator mapsxtonin the range of(-n,n).
Чтобы иметь способ использовать операцию математического модуля, а не
заботиться о знаке перед x можно:
((x % n) + n) % n
Может быть, эта картинка помогает лучше понять это (мне было трудно сначала осмыслить это)
Хороший рисунок. Еще одна сложность: здесь не учитывается модульность 2 ^ 32 самой переменной int. Метод floorMod делает это правильно (но вам могут потребоваться дополнительные вычисления, если значение n отрицательное).
минимальный был бы без скобок;)