Каков самый быстрый способ найти, является ли число четным или нечетным?

каков самый быстрый способ найти, четное или нечетное число?

11 ответов


довольно хорошо известно, что

static inline int is_odd_A(int x) { return x & 1; }

более эффективно, чем

static inline int is_odd_B(int x) { return x % 2; }

но с оптимизатором, будут is_odd_B не отличаться от is_odd_A? Нет-с gcc-4.2 -O2, получаем, (в сборе ARM):

_is_odd_A:
    and r0, r0, #1
    bx  lr

_is_odd_B:
    mov r3, r0, lsr #31
    add r0, r0, r3
    and r0, r0, #1
    rsb r0, r3, r0
    bx  lr

мы видим, что is_odd_B принимает 3 больше инструкций, чем is_odd_A главная причина в том, что

((-1) % 2) == -1
((-1) & 1) ==  1

, все следующие версии будут генерировать тот же код, что и is_odd_A:

#include <stdbool.h>
static inline bool is_odd_D(int x) { return x % 2; }      // note the bool
static inline int  is_odd_E(int x) { return x % 2 != 0; } // note the !=

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


обычный способ сделать это:

int number = ...;
if(number % 2) { odd }
else { even }

альтернатива:

int number = ...;
if(number & 1) { odd }
else { even }

протестировано на GCC 3.3.1 и 4.3.2, оба имеют примерно одинаковую скорость (без оптимизации компилятора), поскольку оба результата в and инструкция (скомпилированные для x86) - я знаю, что с помощью div инструкция по модулю будет намного медленнее, поэтому я ее вообще не тестировал.


bool is_odd = number & 1;

Если (x & 1) истинно, то это странно, иначе это даже.


int i=5;
if ( i%2 == 0 )
{
   // Even
} else {
   // Odd
}

Если это целое число, возможно, просто проверив наименее значимый бит. Ноль будет считаться "даже если".


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

if (x % 2 == 0) // number is even

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

if (x & 0x01 == 0) // number is even

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

  1. вы не в состоянии удовлетворить жесткие производительность требование;
  2. выполняется x % 2 a много (скажем, в узкой петле, которая выполняется тысячи раз);
  3. профилирование указывает на то, что использование оператора mod является узким местом;
  4. профилирование также указывает, что использование побитового-и снимает узкое место и позволяет вам соотвествовать производительности.

int is_odd(int n)
{
   if (n == 0)
      return 0;
   else if (n == 1)
      return 1;
   else
      return !is_odd(n - 1);
}

о, подождите, вы сказали быстрый, не смешной. Мой плохой;)

выше функция работает только для положительных чисел конечно.


проверьте, является ли последний бит 1.

int is_odd(int num) {
  return num & 1;
}

Проверьте наименее значимый бит:

if (number & 0x01) {
  // It's odd
} else {
  // It's even
}

Ваш вопрос не полностью задан. Независимо от этого, ответ зависит от вашего компилятора и архитектуры вашего компьютера. Например, вы на машине используете представление одного или двух подписанных номеров дополнения?

Я пишу свой код, чтобы быть правильным первым, ясным вторым, кратким третьим и быстрым последним. Поэтому я бы закодировал эту процедуру следующим образом:

/* returns 0 if odd, 1 if even */
/* can use bool in C99 */
int IsEven(int n) {
    return n % 2 == 0;
}

этот метод является правильным, Он более четко выражает намерения, чем тестирование LSB, он лаконичен и, верьте или нет, он пылает быстро. Если и только если профилирование скажет мне, что этот метод является узким местом в моем приложении, я подумаю об отклонении от него.