找到一个数字是偶数还是奇数的最快方法是什么?

时间:2010-02-09 12:55:24

标签: c micro-optimization

查找数字是偶数还是奇数的最快方法是什么?

11 个答案:

答案 0 :(得分:54)

众所周知

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

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

但是启用优化器后,is_odd_Bis_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_Bis_odd_A多了3个指令,主要原因是因为

((-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 !=

这是什么意思?优化器通常足够复杂,对于这些简单的东西,最清晰的代码足以保证最佳效率

答案 1 :(得分:7)

通常的做法:

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上编译) - 我知道使用{{1对模数的指令要慢得多,因此我根本没有测试它。

答案 2 :(得分:6)

bool is_odd = number & 1;

答案 3 :(得分:5)

如果(x&amp; 1)为真,那么它是奇数,否则它是偶数。

答案 4 :(得分:2)

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

答案 5 :(得分:2)

如果它是一个整数,可能只需要检查最低有效位。即使如此,零也算在内。

答案 6 :(得分:2)

检查最后一位是否为1。

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

答案 7 :(得分:2)

portable 方式是使用模数运算符%

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

如果你知道你只会在两个补码架构上运行,你可以使用按位和:

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

使用模数运算符会导致相对于按位的代码更慢;但是,除非满足以下所有条件,否则我会坚持下去:

  1. 您未能满足严格的性能要求;
  2. 您正在执行x % 2一个批次(比如在一个被执行数千次的紧密循环中);
  3. 分析表明使用mod运算符是瓶颈;
  4. 分析还表明,使用按位 - 并缓解瓶颈可以满足性能要求。

答案 8 :(得分:1)

您的问题尚未完全说明。无论如何,答案取决于您的编译器和机器的体系结构。例如,您是使用一个补码还是两个补码有符号数表示的机器?

我编写的代码首先是正确的,第二个是清晰的,第三个是简洁的,最后是快速的。因此,我会按如下方式编写此例程:

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

这种方法是正确的,它比测试LSB更清楚地表达了意图,它简洁,不管你信不信,它的速度非常快。当且仅当分析告诉我这个方法是我的应用程序的瓶颈时,我会考虑偏离它。

答案 9 :(得分:1)

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

哦等等,你说最快的方式,而不是最有趣的。我的坏;)

以上功能当然仅适用于正数。

答案 10 :(得分:0)

检查最低有效位:

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