Проверка странности целого числа с помощью оператора по модулю

Следующий фрагмент кода неправильно проверяет странность:

public static boolean isOdd(int i) {
   return i % 2 == 1;
}

Я прочитал в Интернете, что я должен сделать это следующим образом:

public static boolean isOdd(int i) {
   return i % 2 != 0;
}

Почему это?


person casaout    schedule 17.05.2013    source источник
comment
хммм, использование операции по модулю для проверки четности немного излишне   -  person Danubian Sailor    schedule 17.05.2013
comment
Очень важно, что в java нет оператора по модулю. % — оператор остатка. docs.oracle.com/ javase/specs/jls/se7/html/   -  person djeikyb    schedule 18.05.2013
comment
В чем разница между оператором по модулю и оператором остатка?   -  person kaspersky    schedule 17.07.2013


Ответы (6)


Возможно, потому что (i % 2) != 0 работает как с положительными, так и с отрицательными числами.

person Stochastically    schedule 17.05.2013
comment
хороший ответ, но () избыточен, как говорит приоритет оператора Я имею в виду, что вы можете игнорировать его - person Grijesh Chauhan; 17.05.2013
comment
Я не сомневаюсь в тебе, @GrijeshChauhan, но мне проще использовать () намного проще, так что мне не нужно помнить, каковы все правила приоритета операторов во всех языках, которые я выучил в своей жизни! Я думаю, что это также помогает удобочитаемости, потому что устраняет любые сомнения для людей, которые находятся в том же положении, что и я :-). - person Stochastically; 17.05.2013
comment
Да Согласен, () предназначен только для приоритета операций перезаписи и зачем это помнить :) - person Grijesh Chauhan; 17.05.2013

Потому что когда i отрицательное --> (-1) % 2 == -1

person johnchen902    schedule 17.05.2013

Вы должны использовать:

(i & 1) != 0

чтобы избежать проблем со знаком.

Также обратите внимание, что использование & гарантирует, что каким бы глупым ни был компилятор, он никогда не попытается использовать деление для выполнения операции %.

person OldCurmudgeon    schedule 17.05.2013
comment
согласен, i % 1 всегда 0 - person Stochastically; 17.05.2013
comment
Ой! Старший момент - должен был быть i & 1. - person OldCurmudgeon; 17.05.2013
comment
@GradyPlayer воля довольно сильная; данные или этого не произошло. Быстрый тест показал, что Debian GCC 4.4.5 на AMD64 производит идентичную сборку для (i & 1) != 0 и (i % 2) != 0. #include <stdio.h> int main(void) { volatile int i = 1; volatile int j = (i & 1) != 0; printf("%d", j); return j; } (и то же самое с i%2 вместо i&1). cc -S и diff -u говорят, что единственное различие заключается в директиве .file (потому что я создал по одному файлу для каждого). - person user; 18.05.2013
comment
@MichaelKjörling не удивляет, что разработчики компилятора поняли, что оптимизация ... является очень распространенным тестом ... - person Grady Player; 18.05.2013
comment
@GradyPlayer: -O0 в основном означает отсутствие оптимизации. Это хорошо для отладки, но выбор его в качестве основы для тестов... по крайней мере, сомнительно. - person Maciej Piechotka; 18.05.2013
comment
@GradyPlayer Я провел тест как с -O0, так и с -O3 с одинаковым результатом. - person user; 20.05.2013

Первый фрагмент будет работать правильно, если оператор по модулю будет заменен оператором побитового и:

public static boolean isOdd(int i) {
   return (i & 1) == 1;
}
person devnull    schedule 17.05.2013

Это связано с тем, как модуль работает в Java. Если я отрицателен, ответ также будет отрицательным. Каждый отрицательный ввод вернет false.

person treeshakes    schedule 17.05.2013

Поскольку приведенный ниже метод ведет себя правильно при передаче отрицательных, нулевых и положительных значений для каждого числового параметра.

public static boolean isOdd(int i) {
   return i % 2 != 0;
}

Если мы воспользуемся описанным выше методом isOdd(), производительность будет не очень хорошей, лучше использовать побитовый AND operator(&) вместо оператора remainder(%).

 public static boolean isOdd(int i) {
       return (i & 1) != 0;
    }

Этот код работает быстрее, чем первый, в зависимости от того, какую платформу и виртуальную машину мы используем.

Примечание. Как правило, операции деления и остатка выполняются медленнее, чем другие арифметические и логические операции.

person Prags    schedule 05.01.2019