2010-04-21 56 views
13

¿Cuál es la forma más simple de calcular la cantidad de números pares en un rango de enteros sin signo?Manera más simple de calcular la cantidad de números pares en un rango dado

Un ejemplo: si el rango es [0 ... 4], entonces la respuesta es 3 (0,2,4)

Estoy teniendo dificultades para pensar en cualquier forma sencilla. La única solución que surgió involucró un par de declaraciones if. ¿Hay una línea simple de código que puede hacer esto sin declaraciones if o operadores ternarios?

+3

tamaño del rango dividido por dos? –

+0

@Neil, ¿no se aplicaría solo si el rango es siempre '0..x'? –

+2

¿Necesita la etiqueta 'homework'? –

Respuesta

14
int even = (0 == begin % 2) ? (end - begin)/2 + 1 : (end - begin + 1)/2; 

que se puede convertir en:

int even = (end - begin + (begin % 2))/2 + (1 - (begin % 2)); 

EDIT: Esto puede simplificado aún más en:

int even = (end - begin + 2 - (begin % 2))/2; 

Edit2: Debido a la, en mi opinión un tanto incorrecta definición de la división entera en C (división entera trunca hacia abajo para los números positivos y hacia arriba para números negativos) esta fórmula no funcionará cuando comience es un número impar negativo .

Edit3: usuario principiante iPhone 'observa correctamente que si se sustituye con begin % 2begin & 1 esto funcionará correctamente para todos los rangos.

+0

No funciona para el ejemplo del OP, es decir, 0..4 debería devolver 3. –

+0

@Paul R Fencepost error, corregido. –

+0

Parece estar equivocado. Para el ejemplo dado [0..4] 'even = (4 - 0 - (0% 2))/2 = 4/2 = 2'. Creo que 'int even = (end - begin - (begin% 2))/2 + 1;' es la respuesta correcta – SergGr

-3

código Pseudo (No soy un codificador C):

count = 0; 
foreach(i in range){ 
    if(i % 2 == 0){ 
     count++; 
    } 
} 
+3

loop es exagerado aquí – SergGr

+2

O (n) es demasiado caro (... y feo) – Fdr

7

Pista 1: El operador módulo devolverá el resto del número actual
Pista 2: Usted no necesita un bucle
Sugerencia 3: Un rango es continuo
Sugerencia 4: El número de números pares en un rango continuo es la mitad (a veces medio + 1, a veces la mitad - 1)
Sugerencia 5: Construyendo en Pista1: Considere también qué (siendo + fin + 1)% 2 da
Pista 6: La mayor parte o la totalidad de las respuestas en este hilo se equivocan
indicio 7: Asegúrate de probar su solución con número negativo rangos
pizca 8: Asegúrate de probar su solución con rangos que abarcan ambos números negativos y positivos

+0

que lo sé, pero ponerlo en una frase clara es un poco difícil. Dependiendo del rango, puede haber n/2 o n/2 + 1 números pares. – Fdr

+0

@Fdr: Consulte la sugerencia n. ° 1. –

+0

@Fdr: Y considere qué pasaría si lo usara en un punto final. –

0

yo diría que

(max - min + 1 + (min % 2))/2 

Editar: ERM bien por alguna razón pensé que (min% 2) devuelve 1 para los números pares .... :). La versión correcta es

(max - min + 1 + 1 - (min % 2))/2 

o más bien

(max - min + 2 - (min % 2))/2 
+1

¿Qué pasa si 'min' y' max' son ambos 1? – Arkku

+0

Sí, tienes razón, soy tonto. Véase más arriba. – michalburger1

+0

No funciona para (-3, -2) –

2
int start, stop; 
start = 0; 
stop = 9; 
printf("%d",(stop-start)/2+((!(start%2) || !(stop%2)) ? 1 : 0)); 

dónde empezar y parada puede contener cualquier valor. No es necesario repetir para determinar este número.

2

El recuento de los números pares entre 0 y n es [n/2] + 1. Por lo tanto el recuento de los números pares entre (n + 1) y m es ([m/2] + 1) - ([n/2] + 1) = [m/2] - [n/2].

para el recuento de los números pares entre m y n la respuesta, por lo tanto sería [m/2] - [(n - 1)/2].

El [x] se toma en la dirección de - \ infty. Tenga en cuenta que la división común C común no está funcionando bien en nuestro caso: a/2 se redondea hacia cero, no - \ infty, por lo que el resultado no será [a/2] para el caso de negativo.

Este debería ser el cálculo más simple; funciona para números negativos, también. (Sin embargo, necesita que m> = n.) No contiene if sy ?: s.

Si no tenemos en cuenta los números negativos, puede utilizar simplemente m/2 - (n+1)/2 + 1, de lo contrario floor(m/2.0) - floor((n-1)/2.0)

0

La gama es siempre [2a + b, 2c + d] con b, d = {0,1}. Haga una tabla:

b d | #even
0 0 | c-a + 1
0 1 | c-a + 1
1 0 | c-a
1 1 | c-a + 1

Ahora a = min/2, b = min% 2, c = max/2 y d = max% 2.

Así int nEven = max/2 - min/2 + 1 - (min%2)

+0

No funciona para (-3, -2) –

+0

no, no consideré números negativos , mi error –

0

El primer número incluso en el rango es: (begin + 1) & ~1 (ronda begin hasta el número par).

El último número par en el rango es: end & ~1 (redondo end hasta el número par).

El número total de números pares en el rango es por lo tanto: (end & ~1) - ((begin + 1) & ~1) + 1.

int num_evens = (end & ~1) - ((begin + 1) & ~1) + 1; 
+0

¿Está definida la función ~ 1? Buen algoritmo de limpieza, pero no sé de tal función. –

+0

@Kirk: '~' es el operador bit NOT unario en C/C++. Así que '~ 1' es un int con todos menos el bit LS establecido en 1. –

0

Veamos esto lógicamente ...

Tenemos cuatro casos ...

odd -> odd  eg. 1 -> 3 answer: 1 
odd -> even eg. 1 -> 4 answer: 2 
even -> odd eg. 0 -> 3 answer: 2 
even -> even eg. 0 -> 4 answer: 3 

Los tres primeros casos se pueden manejar simplemente como ...

(1 + last - first)/2 

El cuarto caso no cae tan bien en esto, pero podemos eludir en torno a un poco por él con bastante facilidad ...

answer = (1 + last - first)/2; 
if (both first and last are even) 
    answer++; 

Espero que esto ayude.

2

Esto hará el truco, incluso para los rangos con números negativos.

int even = (last - first + 2 - Math.abs(first % 2) - Math.abs(last % 2))/2; 

probado con el siguiente código:

public static void main(String[] args) { 
    int[][] numbers = {{0, 4}, {0, 5}, {1, 4}, {1, 5}, {4, 4}, {5, 5}, 
         {-1, 0}, {-5, 0}, {-4, 5}, {-5, 5}, {-4, -4}, {-5, -5}}; 

    for (int[] pair : numbers) { 
     int first = pair[0]; 
     int last = pair[1]; 
     int even = (last - first + 2 - Math.abs(first % 2) - Math.abs(last % 2))/2; 
     System.out.println("[" + first + ", " + last + "] -> " + even); 
    } 
} 

Salida:

[0, 4] -> 3 
[0, 5] -> 3 
[1, 4] -> 2 
[1, 5] -> 2 
[4, 4] -> 1 
[5, 5] -> 0 
[-1, 0] -> 1 
[-5, 0] -> 3 
[-4, 5] -> 5 
[-5, 5] -> 5 
[-4, -4] -> 1 
[-5, -5] -> 0 
0

Bueno, ¿por qué no:

#include <cassert> 

int ecount(int begin, int end) { 
    assert(begin <= end); 
    int size = (end - begin) + 1; 
    if (size % 2 == 0 || begin % 2 == 1) { 
     return size/2; 
    } 
    else { 
     return size/2 + 1; 
    } 
} 

int main() { 
    assert(ecount(1, 5) == 2); 
    assert(ecount(1, 6) == 3); 
    assert(ecount(2, 6) == 3); 
    assert(ecount(1, 1) == 0); 
    assert(ecount(2, 2) == 1); 
} 
+0

Tiene sentido pero no es una sola línea de código con sentencias' if'. –

+0

Es la solución "más fácil", en mi humilde opinión - que fue la pregunta principal. No veo ninguna razón posible para escribirlo como un trazador de líneas. –

+0

@Neil - ¡hay muchas aquí! ¡Seguramente uno debe ser correcto! ;) prueba el mío, por ejemplo. –

0

La respuesta:

(max - min + 2 - (max % 2) - (min % 2))/2 

Una breve explicación:

  • even..even rendimientos (longitud + 1)/2
  • rendimientos even..odd longitud/2
  • odd..even longitud rendimientos/2
  • rendimientos odd..odd (longitud - 1)/2

  • longitud = max - min + 1

Por lo tanto, la respuesta es (length - 1)/2 más por minuto mínimo más 1/2 para un máx. Tenga en cuenta que (length - 1)/2 == (max - min)/2, y los "bonos" son (1 - (min % 2))/2 y (1 - (max % 2))/2. Resuma todo esto y simplifique para obtener la respuesta anterior.

+0

No funciona para negativos, p. Ej. (-3, -2) –

+0

Derecha. Debería ser: (max - min + 2 - (abs (max)% 2) - (abs (min)% 2))/2. – Bolo

+0

Por otro lado, la pregunta establece explícitamente "un rango de enteros sin signo". – Bolo

1

Estoy un poco sorprendido de que se haya intentado la iteración para resolver esto. El número mínimo de números pares posibles en un rango es igual a la mitad de la longitud de la matriz de números, o, rangeEnd - rangeStart.
Agregue 1 si el primer o el último número es par.

lo tanto, el método es: (usando javascript)

function evenInRange(rangeStart, rangeEnd) 
{ 
    return 
    Math.floor(rangeEnd - rangeStart) + 
    ((rangeStart % 2 == 0) || (rangeEnd % 2 == 0) ? 1 : 0) 
} 


Tests: 
0 1 2 3 4 5 6 7 8 
8 - 0 = 8 
8/2 = 4 
4 + 1 = 5 
Even numbers in range: 
0 2 4 6 8 

11 12 13 14 15 16 17 18 19 20 
20 - 11 = 9 
9/2 = 4 
4 + 1 = 5 
Even numbers in range 
12 14 16 18 20 

1 2 3 
3 - 1 = 2 
2/2 = 1 
1 + 0 = 1 
Even numbers in range 
2 

2 3 4 5 
5 - 2 = 3 
3/2 = 1 
1 + 1 = 2 
Even numbers in range 
2 4 

2 3 4 5 6 
6 - 2 = 4 
4/2 = 2 
2 + 1 = 3 
Even numbers in range 
2 4 6 
+3

Todas sus pruebas se dividen por 2 pero su fórmula no incluye una división en absoluto. –

+1

Estás en lo correcto, debería decir Math.floor ((rangeEnd - rangeStart)/2) Gracias – souLTower

0

En términos de inicio y duración:

(length >> 1) + (1 & ~start & length)

la mitad de la longitud más 1 si inicio es par y la longitud es impar.

En términos de inicio y final:

((end - start + 1) >> 1) + (1 & ~start & ~end)

mitad de la longitud más 1 si inicio es aún y al final es par.

+0

Estoy un poco orgulloso de usar bit a bit AND como un condicional en realidad. :) –

0

Esto no requiere ninguna condición en absoluto:

evencount = floor((max - min)/2) + 1 
Cuestiones relacionadas