Вы бы использовали num% 2 или num & 1, чтобы проверить, является ли число четным? - PullRequest
18 голосов
/ 23 декабря 2009

Ну, есть по крайней мере два низкоуровневых способа определить, является ли данное число четным или нет:

 1. if (num%2 == 0) { /* even */ } 
 2. if ((num&1) == 0) { /* even */ }

Я считаю, что второй вариант гораздо более элегантный и содержательный, и я обычно использую его. Но это не только вопрос вкуса; Фактическая производительность может варьироваться: обычно побитовые операции (такие как логические и здесь) гораздо более эффективны, чем операции с модами (или div). Конечно, вы можете утверждать, что некоторые компиляторы смогут оптимизировать его в любом случае, и я согласен ... но некоторые не будут.

Другой момент заключается в том, что второй может быть немного сложнее понять менее опытным программистам. На это я отвечу, что, вероятно, всем пойдет на пользу, если эти программисты потратят так мало времени, чтобы понять утверждения такого рода.

Что ты думаешь?

Указанные два фрагмента верны, только если num является либо беззнаковым целым числом, либо отрицательным числом с представлением дополнения до двух. - Как справедливо говорится в некоторых комментариях.

Ответы [ 12 ]

0 голосов
/ 23 декабря 2009

Я не думаю, что модуль делает вещи более читабельными. Обе имеют смысл, и обе версии верны. А компьютеры хранят числа в двоичном формате, так что вы можете просто использовать двоичную версию.

Компилятор может заменить версию по модулю более эффективной версией. Но это звучит как оправдание для предпочтения по модулю.

И читаемость в этом особом случае одинакова для обеих версий. Читатель, который плохо знаком с программированием, может даже не знать, что вы можете использовать модуль 2 для определения четности числа. Читатель должен вывести это. Он может даже не знать оператора по модулю !

При выводе значения, стоящего за утверждениями, может быть даже проще прочитать двоичную версию:

if( ( num & 1 ) == 0 ) { /* even */ }
if( ( 00010111b & 1 ) == 0 ) { /* even */ }
if( ( 00010110b & 1 ) == 0 ) { /* odd */ }

(я использовал суффикс "b" только для пояснения, это не C / C ++)

В версии по модулю вы должны дважды проверить, как операция определена в ее деталях (например, проверить документацию, чтобы убедиться, что 0 % 2 - это то, что вы ожидаете).

Двоичный файл AND проще и нет двусмысленностей!

Только операторский приоритет может быть ловушкой с бинарными операторами. Но это не должно быть причиной, чтобы их избегать (когда-нибудь они понадобятся даже новым программистам).

0 голосов
/ 23 декабря 2009

Оба подхода неочевидны, особенно для новичка в программировании. Вы должны определить функцию inline с описательным именем. Подход, который вы используете, не имеет значения (скорее всего, микрооптимизация не сделает вашу программу заметной).

Во всяком случае, я считаю, 2) намного быстрее, так как не требует деления.

...