Pregunta

¿Cómo puedo comprobar si un número determinado es par o impar en C?

¿Fue útil?

Solución

Utilice el operador de módulo (%) para comprobar si hay un resto al dividir por 2:

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

Algunas personas han criticado mi respuesta anterior afirmando que usar x & 1 es "más rápido" o "más eficiente".No creo que este sea el caso.

Por curiosidad, creé dos programas de casos de prueba triviales:

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

Luego los compilé con gcc 4.1.3 en una de mis máquinas 5 veces diferentes:

  • Sin indicadores de optimización.
  • con -O
  • con -Os
  • Con -O2
  • Con -O3

Examiné el resultado del ensamblado de cada compilación (usando gcc -S) y descubrí que en cada caso, el resultado de and.c y módulo.c eran idénticos (ambos usaban la instrucción andl $1, %eax).Dudo que esta sea una característica "nueva" y sospecho que se remonta a versiones antiguas.También dudo que cualquier compilador no arcano moderno (fabricado en los últimos 20 años), comercial o de código abierto, carezca de dicha optimización.Probaría con otros compiladores, pero no tengo ninguno disponible en este momento.

Si alguien más quisiera probar otros compiladores y/o objetivos de plataforma y obtiene un resultado diferente, me interesaría mucho saberlo.

Finalmente, la versión del módulo es garantizado por el estándar para funcionar si el número entero es positivo, negativo o cero, independientemente de la representación de la implementación de enteros con signo.La versión bit a bit y no lo es.Sí, me doy cuenta de que el complemento a dos es algo ubicuo, por lo que esto no es realmente un problema.

Otros consejos

Ustedes son muuuuuuy demasiado eficientes. Lo que realmente quieres es:

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

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

  return odd;
}

Repita para isEven.

Por supuesto, eso no funciona para números negativos. Pero con el brillo viene el sacrificio ...

Use aritmética de bits:

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

Esto es más rápido que usar división o módulo.

[Modo broma = " en "]

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

[Modo broma = " apagado "]

EDITAR: se agregaron valores confusos a la enumeración.

En respuesta a ffpf - Tuve exactamente el mismo argumento con un colega hace años, y la respuesta es no , no funciona con números negativos.

El estándar C estipula que los números negativos se pueden representar de 3 maneras:

  • complemento de 2
  • complemento de 1
  • signo y magnitud

Comprobando así:

isEven = (x & 1);

funcionará para el complemento de 2 y la representación de signo y magnitud, pero no para el complemento de 1.

Sin embargo, creo que lo siguiente funcionará para todos los casos:

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

¡Gracias a ffpf por señalar que el cuadro de texto se estaba comiendo todo después de mi carácter menos que

Una buena es:

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

Tenga en cuenta que este método utiliza la recursividad de cola que involucra dos funciones. Se puede implementar de manera eficiente (convertido en un ciclo while / while) si su compilador admite la recursividad de cola como un compilador de Scheme. ¡En este caso, la pila no debería desbordarse!

Un número es par si, cuando se divide entre dos, el resto es 0. Un número es impar si, cuando se divide entre 2, el resto es 1.

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

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

¡Los métodos son geniales!

i % 2 == 0

Yo diría simplemente dividirlo por 2 y si hay un resto 0, es par, de lo contrario es extraño.

Usar el módulo (%) lo hace fácil.

ej. 4% 2 = 0 por lo tanto 4 es par 5% 2 = 1 por lo tanto 5 es impar

Una solución más al problema
(los niños pueden votar)

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

  }
  return half1 == half2;
}

Construiría una tabla de las paridades (0 si es par, 1 si es impar) de los números enteros (para poder hacer una búsqueda: D), pero gcc no me deja hacer matrices de tales tamaños:

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

Así que recurramos a la definición matemática de par e impar.

Un número entero n es par si existe un número entero k tal que n = 2k.

Un número entero n es impar si existe un número entero k tal que n = 2k + 1.

Aquí está el código para ello:

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

Sean C-enteros los valores posibles de int en una compilación de C determinada.(Tenga en cuenta que los enteros C son un subconjunto de los números enteros).

Ahora bien, uno podría preocuparse de que para un n dado en C-enteros el entero k correspondiente podría no existir dentro de C-enteros.Pero con una pequeña prueba, se puede demostrar que para todos los enteros n, | n | <= | 2n | (*), donde | n | es "n si n es positivo y -n de lo contrario".En otras palabras, para todo n en números enteros se cumple al menos uno de los siguientes (exactamente los casos (1 y 2) o los casos (3 y 4) de hecho, pero no lo probaré aquí):

Caso 1:norte <= 2norte.

Caso 2:-norte <= -2norte.

Caso 3:-norte <= 2norte.

Caso 4:norte <= -2norte.

Ahora toma 2k = n.(Tal k existe si n es par, pero no lo probaré aquí.Si n no es par, entonces el bucle en even no regresa temprano de todos modos, por lo que no importa). Pero esto implica k < n si n no es 0 por (*) y el hecho (nuevamente no probado aquí) de que para todo m, z en números enteros 2m = z implica z no es igual a m dado que m no es 0.En el caso de que n sea 0, 2*0 = 0 entonces 0 es par, hemos terminado (si n = 0 entonces 0 está en C-enteros porque n está en C-enteros en la función even, por lo tanto k = 0 está en C-enteros).Por tanto, tal k en C-enteros existe para n en C-enteros si n es par.

Un argumento similar muestra que si n es impar, existe una k en C-enteros tal que n = 2k + 1.

De ahí las funciones even y odd presentado aquí funcionará correctamente para todos los números enteros C.

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

Aquí hay una respuesta en 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();
}

Pruebe esto: return (((a>>1)<<1) == a)

Ejemplo:

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

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

Al leer esta discusión bastante entretenida, recordé que tenía una función sensible al tiempo del mundo real que evaluaba los números pares e impares dentro del ciclo principal. Es una función de potencia entera, publicada en otro lugar en StackOverflow, de la siguiente manera. Los puntos de referencia fueron bastante sorprendentes. Al menos en esta función del mundo real, el módulo es más lento y significativamente. El ganador, por un amplio margen, que requiere el 67% del tiempo del módulo, es un enfoque o (|) , y no se encuentra en ningún otro lugar de esta página.

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

Para 300 millones de bucles, los tiempos de referencia son los siguientes.

3.962 el | y enfoque de máscara

4.851 el amplificador &; enfoque

5.850 el enfoque%

Para las personas que piensan que la teoría, o una lista de lenguaje ensamblador, resuelve argumentos como estos, esta debería ser una historia de advertencia. Horatio, hay más cosas en el cielo y en la tierra de las que sueñas en tu filosofía.

Este es un seguimiento de la discusión con @RocketRoy sobre su respuesta, pero podría resultar útil para cualquiera que quiera comparar estos resultados.

tl; dr Por lo que he visto, el enfoque de Roy ((0xFFFFFFFF == (x | 0xFFFFFFFE)) no está completamente optimizado para x & 1 como el mod enfoque, pero en la práctica los tiempos de ejecución deberían ser iguales en todos los casos.

Entonces, primero comparé la salida compilada usando Explorador del compilador:

Funciones probadas:

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

Felicitaciones a CLang, se dio cuenta de que los tres casos son funcionalmente iguales.Sin embargo, el enfoque de Roy no está optimizado en GCC, por lo que YMMV.

Es similar con Visual Studio;Al inspeccionar la versión desensamblada x64 (VS2015) para estas tres funciones, pude ver que la parte de comparación es igual para los casos "mod" y "y", y un poco más grande para el caso "o" de Roy:

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

Sin embargo, después de ejecutar un punto de referencia real para comparar estas tres opciones (mod simple, bit a bit o bit a bit y), los resultados fueron completamente iguales (nuevamente, Visual Studio 2005 x86/x64, versión de lanzamiento, sin depurador adjunto).

El conjunto de liberación utiliza el test instrucción para and y mod casos, mientras que el caso de Roy utiliza el cmp eax,0FFFFFFFFh enfoque, pero está muy desarrollado y optimizado, por lo que no hay diferencia en la práctica.

Mis resultados después de 20 ejecuciones (i7 3610QM, plan de energía de Windows 10 configurado en Alto rendimiento):

[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 diferencia entre estas opciones es inferior al 0,3%, por lo que resulta bastante evidente que el montaje es igual en todos los casos.

Aquí está el código si alguien quiere probarlo, con la advertencia de que solo lo probé en Windows (consulte el #if LINUX condicional para el get_time definirlo e implementarlo si es necesario, tomado de esta respuesta).

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

Sé que esto es solo azúcar sintáctico y solo aplicable en .net , pero ¿qué pasa con el método de extensión ...

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

Ahora puedes hacer lo siguiente

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

En la " categoría creativa pero confusa " Ofrezco:

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

Una variante sobre este tema que es específica de 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
    }
}

El método bit a bit depende de la representación interna del entero. El módulo funcionará en cualquier lugar donde haya un operador de módulo. Por ejemplo, algunos sistemas realmente usan los bits de bajo nivel para el etiquetado (como los lenguajes dinámicos), por lo que el amplificador raw x &; 1 en realidad no funcionará en ese caso.

IsOdd (int x) {return true; }

Prueba de corrección: considere el conjunto de todos los enteros positivos y suponga que hay un conjunto de enteros no vacío que no son impares. Debido a que los enteros positivos están bien ordenados, habrá un número más pequeño, no impar, que en sí mismo es bastante extraño, por lo que claramente ese número no puede estar en el conjunto. Por lo tanto, este conjunto no puede estar vacío. Repita para enteros negativos, excepto busque el mayor número no impar.

Portátil:

i % 2 ? odd : even;

Inportable:

i & 1 ? odd : even;

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

Como algunas personas han publicado, hay numerosas formas de hacerlo. De acuerdo con esto sitio web , la forma más rápida es el operador de módulo:

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

Sin embargo, aquí hay algunos otro código marcado por el autor que se ejecutó más lentamente que la operación de módulo común anterior:

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

¿Cuántas personas sabían del Math.System.DivRem o ¿por qué lo usarían?

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

hecho.

Para dar más detalles sobre el método del operador bit a bit para aquellos de nosotros que no hicimos mucho álgebra booleana durante nuestros estudios, aquí hay una explicación. Probablemente no sea de mucha utilidad para el OP, pero tuve ganas de dejar en claro por qué NUMBER & Amp; 1 obras.

Tenga en cuenta que, como alguien respondió anteriormente, la forma en que se representan los números negativos puede detener el funcionamiento de este método. De hecho, incluso puede romper el método del operador de módulo también, ya que cada idioma puede diferir en la forma en que trata los operandos negativos.

Sin embargo, si sabe que NUMBER siempre será positivo, esto funciona bien.

Como Tooony arriba señaló que solo el último dígito en binario (y denary) es importante.

Una lógica Y puerta booleana dicta que ambas entradas tienen que ser un 1 (o alto voltaje) para que 1 sea devuelto.

1 & amplificador; 0 = 0.

0 & amplificador; 1 = 0.

0 & amplificador; 0 = 0.

1 & amplificador; 1 = 1.

Si representa cualquier número como binario (he usado una representación de 8 bits aquí), los números impares tienen 1 al final, los números pares tienen 0.

Por ejemplo:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

Si toma cualquier número y usa Y bit a bit (& amp; en java) por 1, devolverá 00000001, = 1, lo que significa que el número es impar. O 00000000 = 0, lo que significa que el número es par.

Por ejemplo

¿Es extraño?

1 & amplificador; 1 =

00000001 & amp;

00000001 =

00000001 < & # 8212; Impar

2 & amplificador; 1 =

00000010 & amp;

00000001 =

00000000 < & # 8212; Incluso

54 & amplificador; 1 =

00000001 & amp;

00110110 =

00000000 < & # 8212; Incluso

Por eso funciona:

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

Lo siento si esto es redundante.

Número cero paridad | cero http://tinyurl.com/oexhr3k

Secuencia de código de 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))
  

Salida :

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

En aras de la discusión ...

Solo necesita mirar el último dígito en cualquier número dado para ver si es par o impar. Firmado, sin firmar, positivo, negativo: todos son iguales con respecto a esto. Entonces esto debería funcionar en todos los aspectos: -

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 clave aquí está en la tercera línea de código, el operador de división realiza una división entera, por lo que al resultado le falta la parte fraccionaria del resultado. Entonces, por ejemplo, 222/10 dará 22 como resultado. Luego multiplícalo nuevamente con 10 y tendrás 220. Resta eso del original 222 y terminarás con 2, que por arte de magia es el mismo número que el último dígito en el número original. ;-) Los paréntesis están allí para recordarnos el orden en que se realiza el cálculo. Primero, haga la división y la multiplicación, luego reste el resultado del número original. Podríamos dejarlos fuera, ya que la prioridad es más alta para la división y la multiplicación que para la resta, pero esto nos da & Quot; más legible & Quot; código.

Podríamos hacerlo completamente ilegible si quisiéramos. No haría ninguna diferencia para un compilador moderno: -

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

Pero haría el código mucho más difícil de mantener en el futuro. Imagínese que le gustaría cambiar el texto de los números impares a & Quot; ni siquiera es & Quot ;. Luego, otra persona más adelante quiere saber qué cambios realizó y realizar un svn diff o similar ...

Si no le preocupa la portabilidad, sino más bien la velocidad, puede echar un vistazo al bit menos significativo. Si ese bit se establece en 1, es un número impar, si es 0 es un número par. En un pequeño sistema endian, como la arquitectura x86 de Intel, sería algo como esto: -

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

Si quiere ser eficiente, use operadores bit a bit (x & 1), pero si quiere ser legible use el módulo 2 (x % 2)

Verificar pares o impares es una tarea simple.

  

Sabemos que cualquier número exactamente divisible por 2 es un número par más impar.

Solo necesitamos verificar la divisibilidad de cualquier número y para verificar la divisibilidad usamos % operador

Comprobando incluso impar usando if if

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

Programa C para verificar pares o impares usando if más

Uso del operador condicional / ternario

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

C programa para verificar pares o impares usando el operador condicional .

Uso del operador Bitwise

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

+ 66% más rápido > !(i%2) / i%2 == 0

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

El código verifica el último bit del entero si es 1 en binario

Explicación

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

Aviso el bit más a la derecha es siempre 1 para los números impares .

el & amp; bitwise Y el operador verifica el bit más a la derecha en nuestra línea return si es 1

Piense en ello como verdadero & amp; falso

Cuando comparamos n con 1 que significa 0001 en binario (el número de ceros no importa).
entonces imaginemos que tenemos el número entero n con un tamaño de 1 byte.

Se representaría con dígitos binarios de 8 bits / 8.

Si el int n era 7 y lo comparamos con 1 , es como

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

Que F significa falso y T para verdadero.

  

compara solo el bit más a la derecha si ambos son ciertos. Entonces, automáticamente 7 & 1 es T rue.

¿Qué sucede si quiero verificar el bit antes del extremo derecho?

Simplemente cambie n & 1 a n & 2 que 2 representa 0010 en binario y así sucesivamente.

Sugiero usar la notación hexadecimal si eres un principiante en operaciones bit a bit
return n & 1; > > return n & 0x01;.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top