Domanda

Come posso verificare se un dato numero è pari o dispari in C?

È stato utile?

Soluzione

Usa l'operatore modulo (%) per verificare se c'è un resto quando dividi per 2:

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

Alcune persone hanno criticato la mia risposta sopra affermando che usando x & amp; 1 è & Quot; più veloce & Quot; oppure " " più efficiente ;. Non credo che sia così.

Per curiosità, ho creato due banali programmi per test case:

/* 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;
}

Ho quindi compilato questi con gcc 4.1.3 su una delle mie macchine 5 volte diverse:

  • Senza flag di ottimizzazione.
  • Con -O
  • Con -Os
  • Con -O2
  • Con -O3

Ho esaminato l'output dell'assembly di ogni compilazione (usando gcc -S) e ho scoperto che in ogni caso, l'output per and.c e modulo.c erano identici (entrambi hanno usato l'istruzione andl $ 1,% eax). Dubito che questo sia un & Quot; nuovo & Quot; caratteristica, e sospetto che risale alle versioni antiche. Dubito anche che qualsiasi compilatore non arcano moderno (realizzato negli ultimi 20 anni), commerciale o open source, manchi di tale ottimizzazione. Vorrei testare su altri compilatori, ma al momento non ne ho a disposizione.

Se a qualcun altro piacerebbe testare altri compilatori e / o target di piattaforme e ottenere un risultato diverso, sarei molto interessato a saperlo.

Infine, la versione del modulo è garantita dallo standard per funzionare indipendentemente dal fatto che l'intero sia positivo, negativo o zero, indipendentemente dalla rappresentazione dell'implementazione degli interi con segno. La versione bit per bit non lo è. Sì, mi rendo conto che il complemento a due è un po 'onnipresente, quindi questo non è davvero un problema.

Altri suggerimenti

Ragazzi, siete forse troppo efficienti. Quello che vuoi davvero è:

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

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

  return odd;
}

Ripeti per isEven.

Ovviamente, ciò non funziona per i numeri negativi. Ma con lo splendore arriva il sacrificio ...

Usa l'aritmetica dei bit:

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

Questo è più veloce dell'uso di divisione o modulo.

[Modalità scherzo = " su "]

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;
  }
}

[Modalità scherzo = " off "]

EDIT: aggiunti valori confusi all'enum.

In risposta a ffpf - Ho avuto esattamente lo stesso argomento con un collega anni fa e la risposta è no , non funziona con numeri negativi.

Lo standard C stabilisce che i numeri negativi possono essere rappresentati in 3 modi:

  • complemento a 2
  • complemento di 1
  • segno e magnitudine

Verifica in questo modo:

isEven = (x & 1);

funzionerà per il complemento di 2 e la rappresentazione di segni e grandezza, ma non per il complemento di 1.

Tuttavia, credo che quanto segue funzionerà per tutti i casi:

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

Grazie a ffpf per aver sottolineato che la casella di testo stava mangiando tutto dopo il mio personaggio meno che!

Una bella è:

/*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
}

Nota che questo metodo usa la ricorsione della coda che coinvolge due funzioni. Può essere implementato in modo efficiente (trasformato in un po '/ fino al tipo di loop) se il tuo compilatore supporta la ricorsione della coda come un compilatore Scheme. In questo caso lo stack non dovrebbe traboccare!

Un numero è anche se, quando diviso per due, il resto è 0. Un numero è dispari se, quando diviso per 2, il resto è 1.

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

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

I metodi sono fantastici!

i % 2 == 0

Direi semplicemente dividerlo per 2 e se c'è un resto 0, è pari, altrimenti è strano.

L'uso del modulo (%) lo rende facile.

ad es. 4% 2 = 0 quindi 4 è pari 5% 2 = 1 quindi 5 è dispari

Un'altra soluzione al problema
(i bambini sono invitati a votare)

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

  }
  return half1 == half2;
}

Costruirò una tabella delle parità (0 se anche 1 se dispari) degli interi (quindi si potrebbe fare una ricerca: D), ma gcc non mi lascerà fare array di tali dimensioni:

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];
}

Quindi ricorrere invece alla definizione matematica di pari e dispari.

Un numero intero n è anche se esiste un numero intero k tale che n = 2k.

Un numero intero n è dispari se esiste un numero intero k tale che n = 2k + 1.

Ecco il codice per questo:

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;
}

I numeri interi C indicano i possibili valori di int in una data compilazione C. (Si noti che C-interi è un sottoinsieme degli interi.)

Ora ci si potrebbe preoccupare che per un dato n in numeri interi C il numero intero k corrispondente potrebbe non esistere all'interno di numeri C. Ma con una piccola prova si può dimostrare che per tutti gli interi n, | n | < = | 2n | (*), dove | n | è " n se n è positivo e -n altrimenti " ;. In altre parole, per tutte le n in numeri interi almeno una delle seguenti è valida (esattamente sia i casi (1 e 2) che i casi (3 e 4), ma non lo dimostrerò qui):

Caso 1: n < = 2n.

Caso 2: -n < = -2n.

Caso 3: -n < = 2n.

Caso 4: n < = -2n.

Ora prendi 2k = n. (Tale ak esiste se n è pari, ma non lo dimostrerò qui. Se n non è nemmeno allora il ciclo in even non riesce comunque a tornare presto, quindi non importa.) Ma questo implica k < !> lt; n se n non 0 da (*) e il fatto (di nuovo non dimostrato qui) che per tutti m, z in numeri interi 2m = z implica z non uguale a m dato m non è 0. Nel caso n è 0, 2 * 0 = 0, quindi anche 0 è fatto (se n = 0 allora 0 è in numeri interi C perché n è in numero intero C nella funzione odd, quindi k = 0 è in numeri interi C). Quindi tale k in interi C esiste per n in interi C se n è pari.

Un argomento simile mostra che se n è dispari, esiste un k in C-interi tale che n = 2k + 1.

Quindi le funzioni <=> e <=> presentate qui funzioneranno correttamente per tutti i numeri C.

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

Ecco una risposta in 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();
}

Prova questo: return (((a>>1)<<1) == a)

Esempio:

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

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

Leggendo questa discussione piuttosto divertente, mi sono ricordato che avevo una funzione sensibile al tempo reale che verificava i numeri pari e dispari all'interno del ciclo principale. È una funzione di potenza intera, pubblicata altrove su StackOverflow, come segue. I benchmark sono stati abbastanza sorprendenti. Almeno in questa funzione del mondo reale, modulo è più lento , e in modo significativo. Il vincitore, con un ampio margine, che richiede il 67% del tempo di modulo, è un approccio o (|) , e non si trova da nessuna parte in questa pagina.

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;
}

Per 300 milioni di loop, i tempi di riferimento sono i seguenti.

3.962 il | e approccio alla maschera

4.851 l'amplificatore &; approccio

5.850 l'approccio%

Per le persone che pensano che la teoria, o un elenco di lingue assembleari, risolva argomenti come questi, questo dovrebbe essere un ammonimento. Ci sono più cose in cielo e in terra, Orazio, di quanto si sogna nella tua filosofia.

Questo è un seguito alla discussione con @RocketRoy riguardo a la sua risposta , ma potrebbe essere utile a chiunque vuole confrontare questi risultati.

tl; dr Da quanto ho visto, l'approccio di Roy ((0xFFFFFFFF == (x | 0xFFFFFFFE)) non è completamente ottimizzato su x & 1 come l'approccio mod, ma in pratica i tempi di esecuzione dovrebbero risultare uguale in tutti i casi.

Quindi, per prima cosa ho confrontato l'output compilato usando Explorer compilatore :

Funzioni testate:

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 con -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 con -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

Tanto di cappello a CLang, ha capito che tutti e tre i casi sono funzionalmente uguali. Tuttavia, l'approccio di Roy non è ottimizzato in GCC, quindi YMMV.

È simile con Visual Studio; ispezionando lo smontaggio Release x64 (VS2015) per queste tre funzioni, ho potuto vedere che la parte di confronto è uguale per " mod " e " e " casi, e leggermente più grande per il " del Roy; o " caso:

// 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)

Tuttavia, dopo aver eseguito un benchmark effettivo per il confronto di queste tre opzioni (mod semplice, bit a bit o, bit a bit e), i risultati sono stati completamente uguali (di nuovo, Visual Studio 2005 x86 / x64, build di rilascio, nessun debugger collegato).

Il Release Assembly utilizza l'istruzione test per i casi and e cmp eax,0FFFFFFFFh, mentre il caso di Roy utilizza l'approccio #if LINUX, ma è fortemente srotolato e ottimizzato, quindi non vi sono differenze nella pratica.

I miei risultati dopo 20 corse (i7 3610QM, piano di alimentazione di Windows 10 impostato su Prestazioni elevate):

[Test: Plain mod 2 ] AVERAGE TIME: 689.29 ms (Relative diff.: +0.000%)
[Test: Bitwise or  ] AVERAGE TIME: 689.63 ms (Relative diff.: +0.048%)
[Test: Bitwise and ] AVERAGE TIME: 687.80 ms (Relative diff.: -0.217%)

La differenza tra queste opzioni è inferiore allo 0,3%, quindi è abbastanza ovvio che l'assemblaggio è uguale in tutti i casi.

Ecco il codice se qualcuno vuole provare, con un avvertimento che ho provato solo su Windows (controlla il get_time condizionale per la definizione <=> e implementalo se necessario, preso da questa risposta ).

#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;
}

So che questo è solo zucchero sintattico e applicabile solo in .net ma per quanto riguarda il metodo di estensione ...

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

Ora puoi fare quanto segue

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

Nella " categoria creativa ma confusa " Offro:

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

Una variante di questo tema specifica per 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
    }
}

Il metodo bit a bit dipende dalla rappresentazione interna dell'intero. Modulo funzionerà ovunque ci sia un operatore modulo. Ad esempio, alcuni sistemi utilizzano effettivamente i bit di basso livello per il tagging (come i linguaggi dinamici), quindi l'amplificatore x & Grezzo; 1 in realtà non funzionerà in quel caso.

IsOdd (int x) {return true; }

Prova di correttezza: considera l'insieme di tutti i numeri interi positivi e supponi che esista un insieme non vuoto di numeri interi che non sono dispari. Poiché gli interi positivi sono ben ordinati, ci sarà un numero non dispari più piccolo, che di per sé è piuttosto dispari, quindi chiaramente quel numero non può essere nell'insieme. Pertanto, questo set non può essere non vuoto. Ripetere l'operazione per numeri interi negativi tranne cercare il numero massimo non dispari.

Portatile:

i % 2 ? odd : even;

portabile:

i & 1 ? odd : even;

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

Come alcune persone hanno pubblicato, ci sono molti modi per farlo. Secondo questo sito web , il modo più veloce è l'operatore del modulo:

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

Tuttavia, ecco alcune altro codice contrassegnato dal banco dall'autore che ha funzionato più lentamente dell'operazione di modulo comune sopra:

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

Quante persone conoscevano persino metodo Math.System.DivRem o perché dovrebbero usarlo ??

int isOdd(int i){
  return(i % 2);
}

fatto.

Per dare maggiore elaborazione sul metodo dell'operatore bit a bit per quelli di noi che non hanno fatto molta algebra booleana durante i nostri studi, ecco una spiegazione. Probabilmente non è molto utile all'OP, ma mi è sembrato di chiarire perché NUMBER & Amp; 1 funziona.

Nota come quando qualcuno ha risposto sopra, il modo in cui sono rappresentati i numeri negativi può smettere di funzionare questo metodo. In effetti, può anche rompere anche il metodo dell'operatore modulo poiché ogni lingua può differire nel modo in cui tratta gli operandi negativi.

Tuttavia, se sai che NUMBER sarà sempre positivo, questo funziona bene.

Come Tooony sopra ha sottolineato che solo l'ultima cifra in binario (e diniego) è importante.

Una logica AND gate booleana impone che entrambi gli ingressi debbano essere 1 (o alta tensione) per restituire 1.

1 & amp; 0 = 0.

0 & amp; 1 = 0.

0 & amp; 0 = 0.

1 & amp; 1 = 1.

Se rappresenti un numero qualsiasi come binario (qui ho usato una rappresentazione a 8 bit), i numeri dispari hanno 1 alla fine, i numeri pari hanno 0.

Ad esempio:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

Se prendi un numero qualsiasi e usi AND bit per bit (& amp; in java) per 1 restituirà 00000001, = 1 che significa che il numero è dispari. O 00000000 = 0, il che significa che il numero è pari.

es

È dispari?

1 & amp; 1 =

00000001 & amp;

00000001 =

00000001 < & # 8212; Odd

2 & amp; 1 =

00000010 & amp;

00000001 =

00000000 < & # 8212; Anche

54 & amp; 1 =

00000001 & amp;

00110110 =

00000000 < & # 8212; Anche

Ecco perché funziona:

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

Scusate se questo è ridondante.

Parità Numero Zero | zero http://tinyurl.com/oexhr3k

Sequenza di codici 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))
  

Output:

   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
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);
}

Per motivi di discussione ...

Devi solo guardare l'ultima cifra in un dato numero per vedere se è pari o dispari. Firmati, non firmati, positivi, negativi - sono tutti uguali per quanto riguarda questo. Quindi dovrebbe funzionare a tutto tondo: -

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);
  }
}

La chiave qui è nella terza riga di codice, l'operatore di divisione esegue una divisione intera, in modo che al risultato manchi la parte della frazione del risultato. Quindi, ad esempio, 222/10 darà 22 di conseguenza. Quindi moltiplicalo di nuovo per 10 e hai 220. Sottrai quello dal 222 originale e finisci con 2, che per magia è lo stesso numero dell'ultima cifra del numero originale. ;-) Le parentesi sono lì per ricordarci l'ordine in cui viene eseguito il calcolo. Prima fai la divisione e la moltiplicazione, quindi sottrai il risultato dal numero originale. Potremmo lasciarli fuori, poiché la priorità è più alta per divisione e moltiplicazione che per sottrazione, ma questo ci dà & Quot; più leggibile & Quot; codice.

Potremmo rendere tutto illeggibile se lo volessimo. Non farebbe alcuna differenza per un compilatore moderno: -

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

Ma renderebbe il codice molto più difficile da mantenere in futuro. Immagina di voler cambiare il testo per i numeri dispari in & Quot; non è nemmeno & Quot ;. Quindi qualcun altro in seguito vorrà scoprire quali modifiche sono state apportate ed eseguire un svn diff o simile ...

Se non sei preoccupato per la portabilità ma più per la velocità, puoi dare un'occhiata al bit meno significativo. Se quel bit è impostato su 1 è un numero dispari, se è 0 è un numero pari. Su un piccolo sistema endian, come l'architettura x86 di Intel, sarebbe qualcosa del genere: -

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

Se vuoi essere efficiente, usa gli operatori bit per bit (x & 1), ma se vuoi essere leggibile usa il modulo 2 (x % 2)

Il controllo di pari o dispari è un compito semplice.

  

Sappiamo che qualsiasi numero esattamente divisibile per 2 è pari al numero dispari.

Dobbiamo solo verificare la divisibilità di qualsiasi numero e per verificare la divisibilità utilizziamo % operatore

Controllo dispari usando if else

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

Programma C per verificare se dispari o dispari usando if altro

Uso dell'operatore Condizionale / Ternario

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

C programma di controllo pari o dispari mediante operatore condizionale .

Uso dell'operatore Bitwise

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

+ 66% più veloce > !(i%2) / i%2 == 0

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

Il codice controlla l'ultimo bit dell'intero se è 1 in binario

Spiegazione

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...
  

Avviso il bit più a destra è sempre 1 per Dispari .

l'amplificatore &; l'operatore bit per bit AND controlla il bit più a destra nella nostra linea return se è 1

Pensalo come vero & amp; false

Quando confrontiamo n con 1 che significa 0001 in binario (il numero di zeri non ha importanza).
allora immaginiamo di avere l'intero n con una dimensione di 1 byte.

Sarebbe rappresentato da cifre a 8 bit / 8 binarie.

Se int n era 7 e lo confrontiamo con 1 , è come

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

Quale F sta per falso e T vero.

  

confronta solo il bit più a destra se sono entrambi veri. Quindi, automagicamente 7 & 1 è T rue.

E se volessi controllare il bit prima dell'estrema destra?

Cambia semplicemente n & 1 in n & 2 quale 2 rappresenta 0010 in binario e così via.

Suggerisco di usare la notazione esadecimale se sei un principiante alle operazioni bit per bit
return n & 1; > > return n & 0x01;.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top