web-dev-qa-db-ja.com

数が偶数か奇数かを見つける最も速い方法は何ですか?

数が偶数か奇数かを見つける最も速い方法は何ですか?

47
aks

それはかなりよく知られています

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

これは何を意味するのでしょうか?通常、オプティマイザーは十分に洗練されており、これらの単純なものについては最も明確なコードで最高の効率を保証できますです。

57
kennytm

それを行う通常の方法:

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命令を使用するmoduloの方がはるかに遅くなるため、まったくテストしませんでした。

7
AndiDog
bool is_odd = number & 1;
6
digitalarbeiter

(x&1)がtrueの場合は奇数、それ以外の場合は偶数です。

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

portableの方法は、係数演算子%を使用することです。

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

知っている 2の補数アーキテクチャでのみ実行することを知っている場合、ビット単位で使用できます。

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

モジュラス演算子を使用すると、ビット単位に比べてコードが遅くなる可能性があります。ただし、以下のすべてが当てはまらない限り、私はそれを使い続けます。

  1. ハードパフォーマンス要件を満たしていません。
  2. x % 2 a lotを実行しています(たとえば、何千回も実行されているタイトなループで)。
  3. プロファイリングは、mod演算子の使用がボトルネックであることを示しています。
  4. プロファイリングは、ビット単位のANDを使用してボトルネックを軽減することも示していますandを使用すると、パフォーマンス要件を満たすことができます。
2
John Bode

整数の場合、おそらく最下位ビットをチェックするだけです。ゼロとしてもカウントされます。

2
Marcel

最後のビットが1かどうかを確認します。

int is_odd(int num) {
  return num & 1;
}
2
0xfe

あなたの質問は完全に特定されていません。いずれにしても、答えはコンパイラとマシンのアーキテクチャに依存します。たとえば、1の補数または2の補数の符号付き数値表現を使用するマシンを使用していますか?

私は最初に正しく、2番目に明確、3番目に簡潔、最後に速くなるようにコードを記述します。したがって、このルーチンを次のようにコーディングします。

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

この方法は正しく、LSBをテストするよりも目的をより明確に表し、簡潔であり、信じられないかもしれませんが、非常に高速です。この方法が私のアプリケーションのボトルネックであるとプロファイリングで通知された場合にのみ、それから逸脱することを検討します。

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

おもしろいではなく最速とおっしゃいました。私の悪い;)

上記の関数はもちろん正の数に対してのみ機能します。

1
Maurits Rijk

最下位ビットを確認します。

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