saber - ¿Cuál es la forma más rápida de encontrar si un número es par o impar?
numeros impares del 1 al 100 c# (11)
¿Cuál es la forma más rápida de encontrar si un número es par o impar?
Compruebe el bit menos significativo:
if (number & 0x01) {
// It''s odd
} else {
// It''s even
}
Es bastante conocido que
static inline int is_odd_A(int x) { return x & 1; }
es más eficiente que
static inline int is_odd_B(int x) { return x % 2; }
Pero con el optimizador is_odd_B
, ¿ is_odd_B
no será diferente de is_odd_A
? No - con gcc-4.2 -O2
, obtenemos, (en el ensamblaje ARM):
_is_odd_A:
and r0, r0, #1
bx lr
_is_odd_B:
mov r3, r0, lsr #31
add r0, r0, r3
and r0, r0, #1
rsb r0, r3, r0
bx lr
Vemos que is_odd_B
toma 3 instrucciones más que is_odd_A
, la razón principal es porque
((-1) % 2) == -1
((-1) & 1) == 1
Sin embargo , todas las siguientes versiones generarán el mismo código que is_odd_A
:
#include <stdbool.h>
static inline bool is_odd_D(int x) { return x % 2; } // note the bool
static inline int is_odd_E(int x) { return x % 2 != 0; } // note the !=
¿Qué significa esto? El optimizador suele ser lo suficientemente sofisticado como para que, para estas cosas simples, el código más claro sea suficiente para garantizar la mejor eficiencia .
La forma portátil es usar el operador de módulo %
:
if (x % 2 == 0) // number is even
Si sabes que solo vas a ejecutar en las arquitecturas complementarias de dos, puedes usar un bitwise y:
if (x & 0x01 == 0) // number is even
El uso del operador de módulo puede dar como resultado un código más lento en relación con el bit a bit y; sin embargo, me quedaré con él a menos que todo lo siguiente sea verdadero:
- No cumple con un requisito de rendimiento estricto;
- Está ejecutando mucho
x % 2
(por ejemplo, en un ciclo cerrado que se ejecuta miles de veces); - La creación de perfiles indica que el uso del operador de mod es el cuello de botella;
- La creación de perfiles también indica que se usa el bit a bit, y alivia el cuello de botella y le permite cumplir con los requisitos de rendimiento.
La forma usual de hacerlo:
int number = ...;
if(number % 2) { odd }
else { even }
Alternativa:
int number = ...;
if(number & 1) { odd }
else { even }
Probado en GCC 3.3.1 y 4.3.2, ambos tienen aproximadamente la misma velocidad (sin optimización del compilador) ya que ambos dan como resultado la instrucción (compilada en x86) - Sé que usar la instrucción div
para módulo sería mucho más lento, por lo tanto No lo probé en absoluto.
Si se trata de un número entero, probablemente solo verificando el bit menos significativo. Sin embargo, Zero se contabilizaría como tal.
Tu pregunta no está completamente especificada. De todos modos, la respuesta depende de tu compilador y de la arquitectura de tu máquina. Por ejemplo, ¿está en una máquina que usa el complemento de uno o las representaciones de números firmados con dos complementos?
Escribo mi código para que sea correcto primero, claro segundo, conciso tercero y rápido último. Por lo tanto, codificaría esta rutina de la siguiente manera:
/* returns 0 if odd, 1 if even */
/* can use bool in C99 */
int IsEven(int n) {
return n % 2 == 0;
}
Este método es correcto, expresa más claramente el intento que probar el LSB, es conciso y, créalo o no, es increíblemente rápido. Si y solo si el perfil me dijera que este método fue un cuello de botella en mi aplicación, consideraría desviarme de él.
Verifica si el último bit es 1.
int is_odd(int num) {
return num & 1;
}
si (x & 1) es verdadero, entonces es impar, de lo contrario es par.
bool is_odd = number & 1;
int i=5;
if ( i%2 == 0 )
{
// Even
} else {
// Odd
}
int is_odd(int n)
{
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return !is_odd(n - 1);
}
Oh espera, dijiste la manera más rápida, no más divertida . Mi error ;)
La función anterior solo funciona para números positivos, por supuesto.