Какой синтаксис для мода в Java

231

Как пример в псевдокоде:

if ((a mod 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}
боб
источник

Ответы:

357

Вместо оператора по модулю, который имеет немного другую семантику, для неотрицательных целых чисел вы можете использовать оператор остатка% . Для вашего точного примера:

if ((a % 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}

Это может быть упрощено до одной строки:

isEven = (a % 2) == 0;
Коди Хэтч
источник
80
Если / не нужно, просто используйте isEven = (a% 2) == 0,
Стив Куо
59
Осторожнее с терминами mod и modular, потому что 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 предоставляет функции для обоих, а спецификации для них достаточно хорошо объясняют разницу. Также осторожнее с нуля. В математике, хотя ноль является четным числом, он НЕ является положительным или отрицательным.
Джим
4
@ nl-x Вероятно, потому, что лучше четко указывать приоритет, чем оставить его условным. Я, например, не знал, что %оценивается, прежде ==чем я посмотрел его, поэтому было бы неясно, эквивалентно ли выражение (a%2)==0или a%(2==0). Я думаю, это менее важно в Java, где логическое значение не совпадает с целым числом
Мэтью Сэйнсбери
8
Это не оператор модуля - это оператор остатка. Пожалуйста, исправьте пост!
Кирен Джонстон
2
четное булево = ((a & 1) == 0). Намного легче.
mdev
111

Вот представление вашего псевдокода в минимальном коде Java;

boolean isEven = a % 2 == 0;

Теперь я разобью его на составляющие. Оператор модуля в Java является символом процента (%). Поэтому взятие int% int возвращает другое int. Оператор двойного равенства (==) используется для сравнения значений, таких как пара целых, и возвращает логическое значение. Затем он присваивается булевой переменной isEven. На основании приоритета оператора модуль будет оцениваться перед сравнением.

martinatime
источник
12
минимальный был бы без скобок;)
pstanton
3
Это оператор остатка, а не оператор модуля.
Маркиз Лорн
@ user207421 Его имя фактически является оператором остатка, но не являются ли они эквивалентными: « модуль - 4. (вычисления, программирование) Оператор, помещенный между двумя числами, чтобы получить остаток от деления этих чисел».?
GeroldBroser восстанавливает Монику
93

Поскольку все остальные уже дали ответ, я добавлю немного дополнительного контекста. % оператор "модуль" фактически выполняет оставшуюся операцию. Разница между 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);

Здесь я использовал побитовый оператор-and и представил его в краткой форме, показанной в варианте 2. Перезапись его в форме варианта 1 (и, альтернативно, в варианте 3) оставлена ​​читателю в качестве упражнения. ;)

Надеюсь, это поможет.

Роб Ролник
источник
Спасибо, Роб. Эта путаница вызывает огромные трудности при объяснении программистам, как реализовать алгоритмы с математическими свойствами из модульной арифметики. Остаток НЕ является модулем, но можно быстро вывести модуль из остатков.
Джим
1
@TickledPink За исключением того, что это не компилируется в Java.
Евгений
33

Чтобы заставить работу 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;
}
З-Б
источник
12

В Java нет оператора по модулю, как в Си. % в Java является оператором остатка. Для положительных целых чисел он работает точно так же, как и по модулю, но по отрицательным целым числам он работает по-разному и, в отличие от модуля, может работать и с числами с плавающей запятой. Тем не менее, редко использовать% на чем-либо, кроме положительных целых чисел, поэтому, если вы хотите назвать это по модулю, не стесняйтесь!

Грег Чарльз
источник
Но мне нужен один реальный оператор по модулю, который работает и для отрицательных целых чисел, чтобы array[x mod array.length]всегда получать доступ к элементу в моем массиве, а не пытаться индексировать отрицательные позиции.
Крис
2
(x % y + y) % y или начиная с Java 8,Math.floorMod(x, y)
Грег Чарльз
12

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

(a % b + b) % b

Сначала это будет делаться по модулю, ограничивая значение диапазоном -b -> + b, а затем добавляя b, чтобы обеспечить положительное значение, позволяя следующему по модулю ограничить его диапазоном 0 -> b.

Примечание: если b отрицательно, результат также будет отрицательным

Стефан Т
источник
Это может переполниться, когда a и b оба являются большими числами, поэтому это не является правильным решением.
Трикси Вольф
11

Код работает намного быстрее без использования модуля:

public boolean isEven(int a){
    return ( (a & 1) == 0 );
}

public boolean isOdd(int a){
    return ( (a & 1) == 1 );
}
Майкл
источник
3
Это выглядит намного чище, чем принятый ответ. Это не имеет ничего общего с преждевременной оптимизацией. Это просто лучше - если это работает.
AlexWien
4
@LluisMartinez Это одно из самых неверно цитируемых высказываний в области вычислительной техники. Полная цитата: «Программисты тратят огромное количество времени на размышления или беспокойство по поводу скорости некритических частей своих программ, и эти попытки повышения эффективности на самом деле оказывают сильное негативное влияние при рассмотрении вопросов отладки и обслуживания. Мы должны забыть о небольших эффективность, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла. Однако мы не должны упускать наши возможности в эти критические 3% ». Что на самом деле означает что-то совсем другое.
маркиз Лорн
3
@EJP Вы, наверное, правы. Я сделал тест (цикл с 1 миллионом итераций), заняв 4000 наносекунд по модулю, 2500 наносекунд с логическим и.
Луис Мартинес
Почему это будет ответом? Конечно, он нечетный, но ничего не делает с оператором mod / remainder. Вопрос говорит о моде оператора, а не о том, как найти нечетный четный.
Марк Уолш
4

В Java это %оператор: 15.17.3. Остаток Оператор%

Обратите внимание, что floorModв java.lang.Mathклассе также есть результат, отличный от %аргументов с разными знаками:

public static int floorMod​(int x, int y)

Roland
источник
1
Это вызвано тем, что floorMod - лучший оператор по модулю, чем %тот, который также работает должным образом, когда аргумент также отрицателен. Ни один из других ответов на самом деле не является правильным, так как они идут с оговоркой, что% на самом деле не по модулю, если аргументы не являются положительными. В частности, если вы хотите отобразить каждое целое число в последовательную позицию в массиве, то array[floorMod(i, array.length)работает правильно, даже если индекс iпереходит в отрицательную территорию. Не так с %.
Крис
3

Также мод можно использовать так:

int a = 7;
b = a % 2;

bбудет равно 1. Потому что 7 % 2 = 1.

jjnguy
источник
вероятно, ошибочно использовать составные операторы в примере для начинающих и без вывода.
Стю Томпсон
3

Оператор остатка в 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;
}
eljenso
источник
2

Как уже отмечали другие, %оператор (остаток) не совпадает с modоперацией / функцией математического модуля.

mod против %

x mod nФункция отображает xна nв диапазоне [0,n).
В то время как x % nоператор переводит xк nв диапазоне (-n,n).

Чтобы иметь способ использовать операцию математического модуля и не заботиться о знаке перед xодним, можно использовать:

((x % n) + n) % n

Может быть, эта картина помогает лучше понять ее (мне было трудно сначала обдумать это)

введите описание изображения здесь

m4110c
источник
1
Хороший рисунок. Еще одна сложность: здесь не учитывается модульность самой intпеременной 2 ^ 32 . floorModМетод не делает это правильно (но вам могут понадобиться дополнительные расчеты , если nотрицательна).
Мартен Бодевес
1

Другой способ это:

boolean isEven = false;
if((a % 2) == 0)
{
    isEven = true;
}

Но самый простой способ по-прежнему:

boolean isEven = (a % 2) == 0;

Как сказал @Steve Kuo.

brothers28
источник
0

В 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
@WesternGun Это может быть правдой, но если вы знаете, что модуль является положительным, то floorModоперация работает, как ожидалось. Существует также floorModдля longзначений и в противном случае BigIntegerдля больших значений.
Мартен Бодевес
-1

Оператор по модулю% (знак процента). Чтобы проверить на равномерность или вообще сделать по модулю степень 2, вы также можете использовать & (оператор and), например isEven =! (A & 1).

jjrv
источник
-3

Альтернатива коду от @Cody:

Используя оператор модуля:

bool isEven = (a % 2) == 0;

Я думаю, что это немного лучший код, чем писать if / else, потому что меньше дублирования и неиспользуемой гибкости. Это требует немного больше умственных способностей, чтобы исследовать, но хорошее наименование isEvenкомпенсирует.

Джей Базузи
источник
2
Это оператор остатка, а не оператор модуля.
Маркиз Лорн
@ EJP хорошо. Тогда что такое оператор модуля?
TheRealChx101