web-dev-qa-db-ja.com

整数が偶数か奇数かどうかを確認するにはどうすればよいですか。

与えられた数がCで偶数か奇数かをどうやって確認できますか?

193
chustar

2で割ったときに剰余があるかどうかを確認するには、モジュロ(%)演算子を使用します。

if (x % 2) { /* x is odd */ }

X&1を使用する方が「より速い」または「より効率的」であると述べた上で私の答えを何人かの人々が批判しました。これが事実だとは思わない。

好奇心から、私は2つの簡単なテストケースプログラムを作成しました:

/* modulo.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x % 2)
            printf("%d is odd\n", x);
    return 0;
}

/* and.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x & 1)
            printf("%d is odd\n", x);
    return 0;
}

私はそれから5つの異なる時に私のマシンの1つでgcc 4.1.3でこれらをコンパイルしました:

  • 最適化フラグなし。
  • -O付き
  • -Oと
  • -O2あり
  • -O3と

各コンパイルのアセンブリ出力を(gcc -Sを使用して)調べたところ、いずれの場合も、and.cとmodulo.cの出力は同じであることがわかりました(両方ともandl $ 1、%eax命令を使用していました)。これは「新しい」機能ではないかと思いますが、それは古くからあると思います。私はまた、現代(過去20年間に作られた)の難解な非商用コンパイラ(商用またはオープンソース)にもそのような最適化が欠けていることを疑います。他のコンパイラでテストするつもりですが、現時点では利用できるものはありません。

他の誰かが他のコンパイラやプラットフォームターゲットをテストしようとしても、違う結果になるのであれば、私は知ることに非常に興味があります。

最後に、モジュロバージョンは、標準では保証されているで、実装の符号付き整数の表現に関係なく、整数が正、負、またはゼロであるかどうかを処理します。ビットごとのandバージョンは違います。はい、私は2の補数がやや偏在していることを理解しています、それでこれは実際問題ではありません。

449
Chris

あなた達はwaaaaaaaayが効率的すぎる。あなたが本当に欲しいのは:

public boolean isOdd(int num) {
  int i = 0;
  boolean odd = false;

  while (i != num) {
    odd = !odd;
    i = i + 1;
  }

  return odd;
}

isEvenに対して繰り返します。

もちろん、それは負の数には機能しません。しかし輝きと共に犠牲がもたらされます...

208
SCdF

ビット演算を使う:

if((x & 1) == 0)
    printf("EVEN!\n");
else
    printf("ODD!\n");

これは除算や係数を使うよりも速いです。

97
Adam Pierce

[Joke mode = "on"]

public enum Evenness
{
  Unknown = 0,
  Even = 1,
  Odd = 2
}

public static Evenness AnalyzeEvenness(object o)
{

  if (o == null)
    return Evenness.Unknown;

  string foo = o.ToString();

  if (String.IsNullOrEmpty(foo))
    return Evenness.Unknown;

  char bar = foo[foo.Length - 1];

  switch (bar)
  {
     case '0':
     case '2':
     case '4':
     case '6':
     case '8':
       return Evenness.Even;
     case '1':
     case '3':
     case '5':
     case '7':
     case '9':
       return Evenness.Odd;
     default:
       return Evenness.Unknown;
  }
}

[ジョークモード= "オフ"]

編集:enumに分かりにくい値を追加しました。

36
Sklivvz

ffpf - に答えて、私は何年も前に同僚と全く同じ議論をしました、そして答えはnoです、それはしません負の数では動作しません。

C規格では、負の数は3つの方法で表すことができると規定しています。

  • 2の補数
  • 1の補数
  • 符号と大きさ

次のように確認してください。

isEven = (x & 1);

2の補数および符号と大きさの表現に対しては機能しますが、1の補数に対しては機能しません。

しかしながら、私は以下がすべての場合にうまくいくと信じています:

isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));

Ffpfのおかげで、テキストボックスは私の以下の性格の後にすべてを食べていたことを指摘してくれました!

16

いいのは

/*forward declaration, C compiles in one pass*/
bool isOdd(unsigned int n);

bool isEven(unsigned int n)
{
  if (n == 0) 
    return true ;  // I know 0 is even
  else
    return isOdd(n-1) ; // n is even if n-1 is odd
}

bool isOdd(unsigned int n)
{
  if (n == 0)
    return false ;
  else
    return isEven(n-1) ; // n is odd if n-1 is even
}

このメソッドは2つの関数を含む末尾再帰を使用することに注意してください。あなたのコンパイラがSchemeコンパイラのように末尾再帰をサポートしているなら、それは(while/untilループのようなものになる)効率的に実装することができます。この場合、スタックはオーバーフローしてはいけません。

14
Pierre

2で割ったときに剰余が1の場合、数値は偶数になります。2で割ったときに剰余が1の場合、数値は奇数になります。

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

/* C */
int isOdd(int num){
    return num % 2;
}

方法は素晴らしいです!

11
jjnguy
i % 2 == 0
8
Mark Cidade

私はそれを2で割るだけでいい、残りが0であれば偶数で、そうでなければ奇数です。

係数(%)を使用すると、これが簡単になります。

例えば。 4%2 = 0したがって4は偶数5%2 = 1したがって5は奇数

7
Jarod Elliott

整数のパリティ(奇数の場合は1、偶数の場合は1)のテーブルを作成します(そのため、ルックアップを実行できます:D)が、gccではそのようなサイズの配列を作成できません。

typedef unsigned int uint;

char parity_uint [UINT_MAX];
char parity_sint_shifted [((uint) INT_MAX) + ((uint) abs (INT_MIN))];
char* parity_sint = parity_sint_shifted - INT_MIN;

void build_parity_tables () {
    char parity = 0;
    unsigned int ui;
    for (ui = 1; ui <= UINT_MAX; ++ui) {
        parity_uint [ui - 1] = parity;
        parity = !parity;
    }
    parity = 0;
    int si;
    for (si = 1; si <= INT_MAX; ++si) {
        parity_sint [si - 1] = parity;
        parity = !parity;
    }
    parity = 1;
    for (si = -1; si >= INT_MIN; --si) {
        parity_sint [si] = parity;
        parity = !parity;
    }
}

char uparity (unsigned int n) {
    if (n == 0) {
        return 0;
    }
    return parity_uint [n - 1];
}

char sparity (int n) {
    if (n == 0) {
        return 0;
    }
    if (n < 0) {
        ++n;
    }
    return parity_sint [n - 1];
}

それでは、代わりに偶数と奇数の数学的定義に頼りましょう。

整数nは、n = 2kのような整数kが存在していても偶数です。

N = 2k + 1のような整数kが存在する場合、整数nは奇数です。

これがそのコードです。

char even (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k) {
            return 1;
        }
    }
    return 0;
}

char odd (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k + 1) {
            return 1;
        }
    }
    return 0;
}

与えられたCコンパイルでintの可能な値をC整数で表すようにしましょう。 (C整数は整数のサブセットです。)

さて、C整数の与えられたnに対して、対応する整数kがC整数の中に存在しないかもしれないことを心配するかもしれません。しかし、少しの証明で、すべての整数nに対して、| n |であることがわかります。 <= | 2n | (*)、ここで| n | nが正の場合はn、それ以外の場合は-nです。言い換えれば、整数のすべてのnに対して、以下のうちの少なくとも1つが成り立つ(厳密にはケース(1と2)またはケース(3と4)のどちらかだが、ここでは証明しない)。

ケース1:n≦2n。

ケース2:−n≦−2n。

ケース3:−n≦2n。

ケース4:n≦−2n。

今2k = nを取りなさい。 (nが偶数であればそのようなakは存在しますが、ここでは証明しません。nが偶数でなければeven内のループはいずれにしても早く戻ることができないので問題ありません。) nが(*)によって0ではないこと、および整数m 2 = zのzがすべてのmに対してzがmに等しくないことを意味するという事実(ここでも証明されていない)は、nが0でない場合、2 * 0 = 0なので、0でも構いません(n = 0の場合、関数evenではnがC整数であるため、0がC整数になります。したがって、k = 0はC整数になります)。したがって、nが偶数である場合、C整数中のnはC整数中のnに対して存在します。

同様の議論は、nが奇数の場合、n = 2k + 1となるようなC整数の中にkが存在することを示しています。

したがって、ここに示されている関数evenおよびoddは、すべてのC整数に対して正しく機能します。

6
Thomas Eding

問題へのもう一つの解決策
(子供は投票可)

bool isEven(unsigned int x)
{
  unsigned int half1 = 0, half2 = 0;
  while (x)
  {
     if (x) { half1++; x--; }
     if (x) { half2++; x--; }

  }
  return half1 == half2;
}
6
eugensk00

何人かの人々が投稿したように、これをするための多数の方法があります。 このWebサイト によると、最も早い方法はモジュラス演算子です。

if (x % 2 == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

しかし、ここにいくつかの ベンチマークされた他のコード があります。これは上記の一般的なモジュラス演算より遅くなりました。

if ((x & 1) == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

System.Math.DivRem((long)x, (long)2, out outvalue);
        if ( outvalue == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

if (((x / 2) * 2) == x)
               total += 1; //even number
        else
               total -= 1; //odd number

if (((x >> 1) << 1) == x)
               total += 1; //even number
        else
               total -= 1; //odd number

        while (index > 1)
               index -= 2;
        if (index == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

tempstr = x.ToString();
        index = tempstr.Length - 1;
        //this assumes base 10
        if (tempstr[index] == '0' || tempstr[index] == '2' || tempstr[index] == '4' || tempstr[index] == '6' || tempstr[index] == '8')
               total += 1; //even number
        else
               total -= 1; //odd number

Math.System.DivRem メソッドを知っている人もいますか、またはなぜ使うのでしょうか。

5
// C#
bool isEven = ((i % 2) == 0);
5

これは、 彼の答え に関する@RocketRoyとの議論のフォローアップですが、これらの結果を比較したい人にとっては役に立つかもしれません。

tl; drこれまで見てきたことから、Royのアプローチ((0xFFFFFFFF == (x | 0xFFFFFFFE))はmodのアプローチとしてx & 1に完全には最適化されていませんが、実際には実行時間はすべての場合で平等になります。

そこで、最初に Compiler Explorer を使ってコンパイルされた出力を比較しました。

テストされた機能:

int isOdd_mod(unsigned x) {
    return (x % 2);
}

int isOdd_and(unsigned x) {
    return (x & 1);
}

int isOdd_or(unsigned x) {
    return (0xFFFFFFFF == (x | 0xFFFFFFFE));
}   

CLang 3.9.0と-O3:

isOdd_mod(unsigned int):                          # @isOdd_mod(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

isOdd_and(unsigned int):                          # @isOdd_and(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

isOdd_or(unsigned int):                           # @isOdd_or(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

GCC 6.2と-O3:

isOdd_mod(unsigned int):
        mov     eax, edi
        and     eax, 1
        ret

isOdd_and(unsigned int):
        mov     eax, edi
        and     eax, 1
        ret

isOdd_or(unsigned int):
        or      edi, -2
        xor     eax, eax
        cmp     edi, -1
        sete    al
        ret

CLangには、3つのケースすべてが機能的に同等であることがわかりました。しかし、RoyのアプローチはGCCでは最適化されていないので、YMMVです。

Visual Studioと似ています。これら3つの機能について逆アセンブリRelease x64(VS2015)を調べると、比較部分は "mod"と "and"の場合で等しく、Royの "or"の場合でわずかに大きいことがわかります。

// x % 2
test bl,1  
je (some address) 

// x & 1
test bl,1  
je (some address) 

// Roy's bitwise or
mov eax,ebx  
or eax,0FFFFFFFEh  
cmp eax,0FFFFFFFFh  
jne (some address)

ただし、これら3つのオプション(プレーンなmod、bitwiseまたは、bitwise and)を比較するための実際のベンチマークを実行した後、結果は完全に同等でした(これもVisual Studio 2005 x86/x64、リリースビルド、デバッガなし)。

Release Assemblyはtestandの場合にmod命令を使用しますが、Royの場合はcmp eax,0FFFFFFFFhアプローチを使用しますが、展開と最適化が大幅に行われているため、実際には違いはありません。

20回実行した後の結果(i7 3610QM、Windows 10電源プランはHigh Performanceに設定):

 [テスト:Plain mod 2]平均時間:689.29 ms(相対差:+ 0.000%)
 [テスト:ビットごとまたは]平均時間:689.63 ms(相対差:+ 0.048%) ] 
 [テスト:ビットごと]および[平均時間]:687.80ミリ秒(相対差:-0.217%)

これらの選択肢の違いは0.3%未満なので、総会がすべての場合において同等であることは明らかです。

誰かが試してみたい場合のコードは、Windowsでしかテストしていないという警告です(#if LINUX定義のget_time条件をチェックし、必要に応じて実装してください この答え から)。

#include <stdio.h>

#if LINUX
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
    struct timeval t;
    struct timezone tzp;
    gettimeofday(&t, &tzp);
    return t.tv_sec + t.tv_usec*1e-6;
}
#else
#include <windows.h>
double get_time()
{
    LARGE_INTEGER t, f;
    QueryPerformanceCounter(&t);
    QueryPerformanceFrequency(&f);
    return (double)t.QuadPart / (double)f.QuadPart * 1000.0;
}
#endif

#define NUM_ITERATIONS (1000 * 1000 * 1000)

// using a macro to avoid function call overhead
#define Benchmark(accumulator, name, operation) { \
    double startTime = get_time(); \
    double dummySum = 0.0, elapsed; \
    int x; \
    for (x = 0; x < NUM_ITERATIONS; x++) { \
        if (operation) dummySum += x; \
    } \
    elapsed = get_time() - startTime; \
    accumulator += elapsed; \
    if (dummySum > 2000) \
        printf("[Test: %-12s] %0.2f ms\r\n", name, elapsed); \
}

void DumpAverage(char *test, double totalTime, double reference)
{
    printf("[Test: %-12s] AVERAGE TIME: %0.2f ms (Relative diff.: %+6.3f%%)\r\n",
        test, totalTime, (totalTime - reference) / reference * 100.0);
}

int main(void)
{
    int repeats = 20;
    double runningTimes[3] = { 0 };
    int k;

    for (k = 0; k < repeats; k++) {
        printf("Run %d of %d...\r\n", k + 1, repeats);
        Benchmark(runningTimes[0], "Plain mod 2", (x % 2));
        Benchmark(runningTimes[1], "Bitwise or", (0xFFFFFFFF == (x | 0xFFFFFFFE)));
        Benchmark(runningTimes[2], "Bitwise and", (x & 1));
    }

    {
        double reference = runningTimes[0] / repeats;
        printf("\r\n");
        DumpAverage("Plain mod 2", runningTimes[0] / repeats, reference);
        DumpAverage("Bitwise or", runningTimes[1] / repeats, reference);
        DumpAverage("Bitwise and", runningTimes[2] / repeats, reference);
    }

    getchar();

    return 0;
}
4
Lou

このかなりおもしろい議論を読んで、私はメインループの中で奇数と偶数をテストする現実世界の、時間に敏感な機能を持っていたことを思い出しました。これは、以下のようにStackOverflowの他の場所に投稿された整数べき乗関数です。ベンチマークは非常に驚くべきものでした。少なくともこの実世界の関数では、モジュロは遅い、そしてかなりそうです。 勝者は、モジュロの67%の時間を必要としますが、or(|)アプローチであり、このページの他の場所にはありません。

static dbl  IntPow(dbl st0, int x)  {
    UINT OrMask = UINT_MAX -1;
    dbl  st1=1.0;
    if(0==x) return (dbl)1.0;

    while(1 != x)   {
        if (UINT_MAX == (x|OrMask)) {     //  if LSB is 1...    
        //if(x & 1) {
        //if(x % 2) {
            st1 *= st0;
        }    
        x = x >> 1;  // shift x right 1 bit...  
        st0 *= st0;
    }
    return st1 * st0;
}

3億ループの場合、ベンチマークのタイミングは次のとおりです。

3.962とマスクアプローチ

4.851&アプローチ

5.850%アプローチ

理論、またはアセンブリ言語のリストをこれらのような議論を解決すると考える人々にとって、これは注意深い物語であるはずです。天と地、ホレイショには、あなたの哲学で夢見ているものよりももっと多くのものがあります。

4
user1899861

これを試してください:return (((a>>1)<<1) == a)

例:

a     =  10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010

b     =  10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100
4

これがJavaでの答えです。

public static boolean isEven (Integer Number) {
    Pattern number = Pattern.compile("^.*?(?:[02]|8|(?:6|4))$");
    String num = Number.toString(Number);
    Boolean numbr = new Boolean(number.matcher(num).matches());
    return numbr.booleanValue();
}
4
Thomas Eding

「クリエイティブだが紛らわしいカテゴリ」では、

int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }

このテーマの変形で、Microsoft C++に特有のものです。

__declspec(naked) bool __fastcall isOdd(const int x)
{
    __asm
    {
        mov eax,ecx
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        ret
    }
}
3
DocMax

これは単なる構文上の糖であり、は.netにのみ適用可能ですが、拡張方法はどうでしょうか。

public static class RudiGroblerExtensions
{
    public static bool IsOdd(this int i)
    {
        return ((i % 2) != 0);
    }
}

今、あなたは以下をすることができます

int i = 5;
if (i.IsOdd())
{
    // Do something...
}
3
rudigrobler

ビット単位の方法は整数の内部表現に依存します。モジュロはモジュロ演算子があるところならどこでも動作します。例えば、(動的言語のように)実際にはタグ付けに低レベルのビットを使用するシステムもあるので、生のx&1は実際にはそのような場合には動作しません。

2
Will Hartung

IsOdd(int x){trueを返します。 }

正当性の証明 - すべての正の整数の集合を考え、奇数ではない空でない整数の集合があるとします。正の整数は整然とした順序なので、奇数ではなく最小の数があります。それ自体はかなり奇数なので、明らかにその数をセットに含めることはできません。したがって、このセットを空にすることはできません。最大で奇数でないことを除いて、負の整数で繰り返します。

2
plinth

ポータブル:

i % 2 ? odd : even;

持ち運び不可能:

i & 1 ? odd : even;

i << (BITS_PER_INT - 1) ? odd : even;
2
ilitirit

数値ゼロパリティゼロ http://tinyurl.com/oexhr3k

Pythonコードシーケンス.

# defining function for number parity check
def parity(number):
    """Parity check function"""
    # if number is 0 (zero) return 'Zero neither ODD nor EVEN',
    # otherwise number&1, checking last bit, if 0, then EVEN, 
    # if 1, then ODD.
    return (number == 0 and 'Zero neither ODD nor EVEN') \
            or (number&1 and 'ODD' or 'EVEN')

# cycle trough numbers from 0 to 13 
for number in range(0, 14):
    print "{0:>4} : {0:08b} : {1:}".format(number, parity(number))

出力:

   0 : 00000000 : Zero neither ODD nor EVEN
   1 : 00000001 : ODD
   2 : 00000010 : EVEN
   3 : 00000011 : ODD
   4 : 00000100 : EVEN
   5 : 00000101 : ODD
   6 : 00000110 : EVEN
   7 : 00000111 : ODD
   8 : 00001000 : EVEN
   9 : 00001001 : ODD
  10 : 00001010 : EVEN
  11 : 00001011 : ODD
  12 : 00001100 : EVEN
  13 : 00001101 : ODD
1
user1630938
int isOdd(int i){
  return(i % 2);
}

行った。

1
None

私たちの研究の間にあまりブール代数をしなかった私たちの人々のためにビットごとの演算子方法についてもっと詳しく述べるために、ここに説明があります。おそらくOPにはあまり役に立ちませんが、NUMBER&1が機能する理由を明確にしたいと思いました。

誰かが上で答えたように、負の数が表される方法はこの方法が機能するのを止める可能性があることに注意してください。実際、各言語は負のオペランドの扱い方が異なるため、モジュロ演算子の方法でさえも破られる可能性があります。

しかし、NUMBERが常に正であることを知っていれば、これはうまくいきます。

Tooonyが上で述べたように、2進数(および否定)の最後の数字だけが重要であるという点を指摘しました。

ブール論理ANDゲートは、1を返すには両方の入力を1(または高電圧)にする必要があることを示しています。

1&0 = 0.

0&1 = 0.

0&0 = 0.

1&1 = 1.

任意の数を2進数で表すと(ここでは8ビット表現を使用しています)、奇数は最後に1が、偶数は0になります。

例えば:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

任意の数値を取り、1ずつビット単位のAND(Javaでは&)を使用すると、00000001、= 1が返されます。これは、数値が奇数であることを意味します。または00000000 = 0、数値が偶数であることを意味します。

例えば

変ですか?

1&1 =

00000001&

00000001 =

00000001 < - 奇数

2&1 =

00000010&

00000001 =

00000000 < - 偶数

54&1 =

00000001&

00110110 =

00000000 < - 偶数

これがこれが機能する理由です。

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

これが冗長な場合は申し訳ありません。

1
Astridax
I execute this code for ODD & EVEN:

#include <stdio.h>
int main()
{
    int number;
    printf("Enter an integer: ");
    scanf("%d", &number);

    if(number % 2 == 0)
        printf("%d is even.", number);
    else
        printf("%d is odd.", number);
}
1
Omar Faruk

偶数または奇数のチェックは簡単な作業です。

2で正確に割り切れる数は偶数、それ以外は奇数であることがわかります。

任意の数の可分性をチェックする必要があり、可分性をチェックするためには%演算子を使用します

if elseを使って偶数をチェックする

if(num%2 ==0)  
{
    printf("Even");
}
else
{
    printf("Odd");
}

もしそうでなければ偶数または奇数をチェックするCプログラム

条件付き/三項演算子を使用する

(num%2 ==0) printf("Even") : printf("Odd");

条件演算子を使用して偶数または奇数をチェックするCプログラム

ビット演算子を使う

if(num & 1)  
{
    printf("Odd");
}
else 
{
    printf("Even");
}
0
Pankaj Prakash

+ 66%速い> !(i%2) / i%2 == 0

int isOdd(int n)
{
    return n & 1;
}

コードは、バイナリの1の場合、整数の最後のビットをチェックします。

説明

Binary  :   Decimal
-------------------
0000    =   0
0001    =   1
0010    =   2
0011    =   3
0100    =   4
0101    =   5
0110    =   6
0111    =   7
1000    =   8
1001    =   9
and so on...

注意一番右のビットは常に1です。奇数数字。

ビットごとのAND演算子は、return行の右端のビットが1であればチェックします。

それを真と偽と考える

n1を比較すると、2進数で0001を意味します(ゼロの数は関係ありません)。
次に、1バイトのサイズを持つ整数nがあるとしましょう。

それは8ビット/ 8バイナリの数字で表現されるでしょう。

Int n7で、1と比較すると、

7 (1-byte int)|    0  0  0  0    0  1  1  1
       &
1 (1-byte int)|    0  0  0  0    0  0  0  1
********************************************
Result        |    F  F  F  F    F  F  F  T

これはFがfalseを表し、Tがtrueを表します。

それは比較するそれらが両方とも真であるならば最も右のビットだけです。したがって、自動的に7 & 1T rueです。

一番右の前のビットをチェックしたい場合はどうすればいいですか?

n & 1n & 2に変更するだけです。2はバイナリで0010を表します。

ビット演算の初心者であれば、16進数表記を使用することをお勧めします。
return n & 1; >> return n & 0x01;

0
X Stylish

議論のために...

あなたはそれが偶数か奇数かを確かめるために与えられた数の最後の数字を見る必要があるだけです。符号付き、符号なし、正、負 - これに関してはすべて同じです。だからこれはすべてのラウンドで動作するはずです -

void tellMeIfItIsAnOddNumberPlease(int iToTest){
  int iLastDigit;
  iLastDigit = iToTest - (iToTest / 10 * 10);
  if (iLastDigit % 2 == 0){
    printf("The number %d is even!\n", iToTest);
  } else {
    printf("The number %d is odd!\n", iToTest);
  }
}

ここで重要なのは3行目のコードです。除算演算子は整数除算を実行するので、結果には結果の小数部分が欠けています。そのため、例えば222/10は結果として22になります。それから10でそれを再び掛けてください、そしてあなたは220を持っています。オリジナルの222からそれを引くと2で終わります。これは魔法によってオリジナルの数字の最後の数字と同じ数字です。 ;-)計算が行われる順序を思い出させるために括弧があります。最初に除算と乗算を行い、次に元の数から結果を引きます。優先順位は減算よりも除算と乗算の方が高いので、私たちはそれらを除外することができました、しかしこれは私たちに「もっと読みやすい」コードを与えます。

私たちが望めば私たちはそれをすべて完全に読めなくすることができます。それは現代のコンパイラにはまったく違いはありません: -

printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");

しかし、それは将来コードを維持することをより困難にするでしょう。奇数のテキストを「偶数ではない」に変更したいと想像してください。それから後になって他の誰かがあなたがどんな変更を加えたのかを知りたい、そしてsvn diffかそれに類似したものを実行したいのですが….

移植性について心配していないが速度についてもっと心配しているなら、あなたは最下位ビットを見ることができるでしょう。そのビットが1に設定されている場合、それは奇数であり、それが0である場合、それは偶数です。 Intelのx86アーキテクチャのようなリトルエンディアンのシステムでは、このようなものになるでしょう -

if (iToTest & 1) {
  // Even
} else {
  // Odd
}
0
Tooony

効率的にしたい場合はビット演算子(x & 1)を使用しますが、読み取り可能にしたい場合はモジュロ2(x % 2)を使用します。

0
Vihung