¿Cómo puedo verificar si un entero es par o impar?

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

Use el operador módulo (%) para verificar si hay un rest al dividir por 2:

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

Algunas personas han criticado mi respuesta anterior al afirmar que usar x y 1 es “más rápido” o “más eficiente”. No creo que este sea el caso.

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

 /* modulo.c */ #include  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  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 banderas de optimización.
  • Con -O
  • Con -Os
  • Con -O2
  • Con -O3

Examiné la salida del ensamblaje de cada comstackción (usando gcc -S) y encontré que en cada caso, la salida para and.c y modulo.c era idéntica (ambos usaron la instrucción andl $ 1,% eax). Dudo que esta sea una característica "nueva", y sospecho que data de versiones antiguas. También dudo que cualquier comstackdor no arcano moderno (hecho en los últimos 20 años), comercial o de código abierto, carezca de tal optimización. Probaría en otros comstackdores, pero no tengo ninguno disponible en este momento.

Si alguien más quisiera probar otros comstackdores y / o objectives de la plataforma, y ​​obtiene un resultado diferente, estaría muy interesado en saberlo.

Finalmente, la versión de módulo está garantizada por el estándar para que funcione si el entero es positivo, negativo o cero, independientemente de la representación de la implementación de enteros con signo. El bit a bit y la versión no. Sí, me doy cuenta de que el complemento de dos es algo omnipresente, así que esto no es realmente un problema.

Ustedes son 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 shinyz viene el sacrificio …

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

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

[Modo de broma = “apagado”]

EDITAR: Agregó 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 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 estaba comiendo todo después de mi personaje 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 recursividad de cola que implica dos funciones. Se puede implementar de manera eficiente (convertida en un ciclo while / until of) si el comstackdor admite recursión de cola como un comstackdor Scheme. ¡En este caso, la stack no debería desbordarse!

Un número es incluso si, cuando se divide por dos, el rest es 0. Un número es impar si, cuando se divide por 2, el rest 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 que solo lo divide por 2 y si hay un 0 restante, es par, de lo contrario es extraño.

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

p.ej. 4% 2 = 0, por lo tanto, 4 es incluso 5% 2 = 1, por lo tanto, 5 es impar

Una solución más al problema
(los niños son bienvenidos a 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 que 1 si es impar) de los enteros (por lo que se podría hacer una búsqueda: D), pero gcc no me permitirá crear 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, en cambio, recurramos a la definición matemática de par e impar.

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

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

Deje C-enteros denotan los valores posibles de int en una comstackción de C dada. (Tenga en cuenta que C-enteros es un subconjunto de los enteros).

Ahora uno podría preocuparse de que para una n dada en C-enteros, el entero correspondiente k podría no existir dentro de C-enteros. Pero con un poco de prueba, se puede mostrar 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 al menos uno de los siguientes (exactamente casos (1 y 2) o casos (3 y 4) de hecho, pero no lo demostraré aquí):

Caso 1: n <= 2n.

Caso 2: -n <= -2n.

Caso 3: -n <= 2n.

Caso 4: n <= -2n.

Ahora toma 2k = n. (Tal ak existe si n es par, pero no lo probaré aquí. Si n no es par, incluso el bucle no regresa temprano de todos modos, así que no importa). Pero esto implica k even , de ahí que k = 0 está en C-enteros). Por lo tanto, tal ak en C-enteros existe para n en C-enteros si n es par.

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

Por lo tanto, las funciones even e odd presentadas aquí funcionarán correctamente para todos los enteros en C.

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

Como algunas personas han publicado, existen numerosas formas de hacerlo. Según este 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 otro código que fue banco marcado por el autor que corrió más lento 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 conocían el método Math.System.DivRem o por qué lo usarían?

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

Intenta 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 real y sensible al tiempo que probaba los números impares y pares 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, módulo es más lento y significativamente más. El ganador, por un amplio margen, que requiere el 67% del tiempo del módulo, es un enfoque o (|) , y no se encuentra en ninguna otra parte 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 enfoque &

5.850 el enfoque%

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

Este es un seguimiento de la discusión con @RocketRoy con respecto a su respuesta , pero podría ser ú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 enfoque mod , pero en la práctica los tiempos de ejecución deberían ser iguales en todos los casos.

Entonces, primero comparé la salida comstackda usando el comstackdor Explorer :

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; inspeccionando el desassembly Release 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 (simple mod, bitwise o bitwise and), los resultados fueron completamente iguales (una vez más, Visual Studio 2005 x86 / x64, Release build, sin depurador adjunto).

El ensamblaje de liberación usa la instrucción de test para cmp eax,0FFFFFFFFh mod cases, mientras que el caso de Roy usa el enfoque cmp eax,0FFFFFFFFh , pero está muy desenrollado 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 establecido en Alto rendimiento):

 [Prueba: simple mod 2] TIEMPO PROMEDIO: 689.29 ms (Dif. Relativa .: + 0.000%)
 [Prueba: en bits o] TIEMPO PROMEDIO: 689.63 ms (Diferencia relativa: + 0.048%)
 [Prueba: en bits y] TIEMPO PROMEDIO: 687.80 ms (Diferencia relativa: -0.217%)

La diferencia entre estas opciones es inferior al 0,3%, por lo que es bastante obvio que el conjunto es igual en todos los casos.

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

 #include  #if LINUX #include  #include  double get_time() { struct timeval t; struct timezone tzp; gettimeofday(&t, &tzp); return t.tv_sec + t.tv_usec*1e-6; } #else #include  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 de 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. Modulo funcionará en cualquier lugar donde haya un operador de módulo. Por ejemplo, algunos sistemas realmente usan los bits de bajo nivel para etiquetar (como los lenguajes dynamics), por lo que el x y el 1 en bruto no funcionarán 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 no vacío de enteros 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 ser no vacío. Repita para enteros negativos excepto buscar el mayor número no impar.

Portátil:

 i % 2 ? odd : even; 

Unportable:

 i & 1 ? odd : even; i << (BITS_PER_INT - 1) ? odd : even; 
 int isOdd(int i){ return(i % 2); } 

hecho.

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

Tenga en cuenta que, como alguien respondió anteriormente, la forma en que se representan los números negativos puede evitar que este método funcione. De hecho, incluso puede romper el método del operador del módulo, ya que cada idioma puede diferir en cómo se maneja con los operandos negativos.

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

Como Tooony arriba hizo el punto que solo el último dígito en binario (y denary) es importante.

Una puerta AND lógica booleana dicta que ambas entradas deben ser 1 (o alta tensión) para que se devuelva 1.

1 y 0 = 0.

0 y 1 = 0.

0 y 0 = 0.

1 y 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 utiliza Y (y en java) bit a bit en 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.

P.ej

¿Es impar?

1 y 1 =

00000001 y

00000001 =

00000001 <- Par

2 y 1 =

00000010 y

00000001 =

00000000 <- Even

54 y 1 =

00000001 y

00110110 =

00000000 <- Even

Es por eso que esto funciona:

 if(number & 1){ //Number is odd } else { //Number is even } 

Lo siento si esto es redundante.

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

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

For the sake of discussion…

You only need to look at the last digit in any given number to see if it is even or odd. Signed, unsigned, positive, negative – they are all the same with regards to this. So this should work all round: –

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

The key here is in the third line of code, the division operator performs an integer division, so that result are missing the fraction part of the result. So for example 222 / 10 will give 22 as a result. Then multiply it again with 10 and you have 220. Subtract that from the original 222 and you end up with 2, which by magic is the same number as the last digit in the original number. 😉 The parenthesis are there to remind us of the order the calculation is done in. First do the division and the multiplication, then subtract the result from the original number. We could leave them out, since the priority is higher for division and multiplication than of subtraction, but this gives us “more readable” code.

We could make it all completely unreadable if we wanted to. It would make no difference whatsoever for a modern compiler: –

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

But it would make the code way harder to maintain in the future. Just imagine that you would like to change the text for odd numbers to “is not even”. Then someone else later on want to find out what changes you made and perform a svn diff or similar…

If you are not worried about portability but more about speed, you could have a look at the least significant bit. If that bit is set to 1 it is an odd number, if it is 0 it’s an even number. On a little endian system, like Intel’s x86 architecture it would be something like this: –

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

If you want to be efficient, use bitwise operators ( x & 1 ), but if you want to be readable use modulo 2 ( x % 2 )

Checking even or odd is a simple task.

We know that any number exactly divisible by 2 is even number else odd.

We just need to check divisibility of any number and for checking divisibility we use % operator

Checking even odd using if else

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

C program to check even or odd using if else

Using Conditional/Ternary operator

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

C program to check even or odd using conditional operator .

Using Bitwise operator

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

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

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

The code checks the last bit of the integer if it’s 1 in Binary

Explanation

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

Notice the rightmost bit is always 1 for Odd numbers.

the & bitwise AND operator checks the rightmost bit in our return line if it’s 1

Think of it as true & false

When we compare n with 1 which means 0001 in binary (number of zeros doesn’t matter).
then let’s just Imagine that we have the integer n with a size of 1 byte.

It’d be represented by 8-bit / 8-binary digits.

If the int n was 7 and we compare it with 1 , It’s like

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

Which F stands for false and T for true.

It compares only the rightmost bit if they’re both true. So, automagically 7 & 1 is T rue.

What if I want to check the bit before the rightmost?

Simply change n & 1 to n & 2 which 2 represents 0010 in Binary and so on.

I suggest using hexadecimal notation if you’re a beginner to bitwise operations
return n & 1; >> return n & 0x01; .